From ca7297b86673cf06c7089a962b763abb246ec4d5 Mon Sep 17 00:00:00 2001 From: Violet Date: Mon, 25 Oct 2021 21:35:45 -0400 Subject: [PATCH 001/223] remove requirement of T: Debug from Weak --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 493cf3117edf..45333f38d8fc 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2393,7 +2393,7 @@ impl Clone for Weak { } #[stable(feature = "rc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(Weak)") } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index b75e9a2f3c71..a3422fb93c87 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -303,7 +303,7 @@ impl, U: ?Sized> CoerceUnsized> for Weak {} impl, U: ?Sized> DispatchFromDyn> for Weak {} #[stable(feature = "arc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { +impl fmt::Debug for Weak { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(Weak)") } From b8d560c19015b9d44f84d6f0396cf713b30f4db7 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Sat, 15 Oct 2022 19:03:54 -0700 Subject: [PATCH 002/223] Stabilize `main_separator_str` Signed-off-by: Alex Saveau --- library/std/src/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 9d63281627d6..b3468e6234b0 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -271,7 +271,7 @@ pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP; /// The primary separator of path components for the current platform. /// /// For example, `/` on Unix and `\` on Windows. -#[unstable(feature = "main_separator_str", issue = "94071")] +#[stable(feature = "main_separator_str", since = "CURRENT_RUSTC_VERSION")] pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR; //////////////////////////////////////////////////////////////////////////////// From 72a9029b84d0c2dcf10cee08d39f8a64964df22d Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 6 Nov 2022 16:08:05 -0800 Subject: [PATCH 003/223] PhantomData layout guarantees --- library/core/src/marker.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index ae4ebf444429..26b7dddcd2e5 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -621,6 +621,12 @@ impl !Sync for *mut T {} /// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so /// as not to indicate ownership. /// +/// ## Layout +/// +/// For all `T`, the following are guaranteed: +/// * `size_of::>() == 0` +/// * `align_of::>() == 1` +/// /// [drop check]: ../../nomicon/dropck.html #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] From ac583f18b75f005023b41d49298d4d343740648a Mon Sep 17 00:00:00 2001 From: Markus Everling Date: Thu, 1 Dec 2022 12:21:12 +0100 Subject: [PATCH 004/223] Add O(1) `Vec -> VecDeque` conversion guarantee --- library/alloc/src/collections/vec_deque/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4866c53e7d52..0645f2ae4da8 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2794,9 +2794,9 @@ impl From> for VecDeque { /// [`Vec`]: crate::vec::Vec /// [`VecDeque`]: crate::collections::VecDeque /// - /// In its current implementation, this is a very cheap - /// conversion. This isn't yet a guarantee though, and - /// shouldn't be relied on. + /// This conversion is guaranteed to run in *O*(1) time + /// and to not re-allocate the `Vec`'s buffer or allocate + /// any additional memory. #[inline] fn from(other: Vec) -> Self { let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc(); From 9553a4d439ffcf239c12142a78aa9923058e8a78 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 9 Dec 2022 17:23:09 -0800 Subject: [PATCH 005/223] Fix process-panic-after-fork.rs to pass on newer versions of Android. The test process-panic-after-fork.rs was checking that abort() resulted in SIGSEGV on Android. This non-standard behavior was fixed back in 2013, so let's fix the test to also accept the standard behavior on Android. --- .../ui/process/process-panic-after-fork.rs | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs index 6d4d24922253..da2683121735 100644 --- a/src/test/ui/process/process-panic-after-fork.rs +++ b/src/test/ui/process/process-panic-after-fork.rs @@ -84,42 +84,47 @@ fn expect_aborted(status: ExitStatus) { #[cfg(target_os = "android")] { - // Android signals an abort() call with SIGSEGV at address 0xdeadbaad - // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc - assert!(signal == libc::SIGSEGV); + assert!(signal == libc::SIGABRT || signal == libc::SIGSEGV); - // Additional checks performed: - // 1. Find last tombstone (similar to coredump but in text format) from the - // same executable (path) as we are (must be because of usage of fork): - // This ensures that we look into the correct tombstone. - // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad. - // 3. libc::abort call is in one of top two functions on callstack. - // The last two steps distinguish between a normal SIGSEGV and one caused - // by libc::abort. + if signal == libc::SIGSEGV { + // Pre-KitKat versions of Android signal an abort() with SIGSEGV at address 0xdeadbaad + // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc + // + // This behavior was changed in KitKat to send a standard SIGABRT signal. + // See: https://r.android.com/60341 + // + // Additional checks performed: + // 1. Find last tombstone (similar to coredump but in text format) from the + // same executable (path) as we are (must be because of usage of fork): + // This ensures that we look into the correct tombstone. + // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad. + // 3. libc::abort call is in one of top two functions on callstack. + // The last two steps distinguish between a normal SIGSEGV and one caused + // by libc::abort. - let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap(); - let exe_string = format!(">>> {this_exe} <<<"); - let tombstone = (0..100) - .map(|n| format!("/data/tombstones/tombstone_{n:02}")) - .filter(|f| std::path::Path::new(&f).exists()) - .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file")) - .filter(|f| f.contains(&exe_string)) - .last() - .expect("no tombstone found"); + let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap(); + let exe_string = format!(">>> {this_exe} <<<"); + let tombstone = (0..100) + .map(|n| format!("/data/tombstones/tombstone_{n:02}")) + .filter(|f| std::path::Path::new(&f).exists()) + .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file")) + .filter(|f| f.contains(&exe_string)) + .last() + .expect("no tombstone found"); - println!("Content of tombstone:\n{tombstone}"); + println!("Content of tombstone:\n{tombstone}"); - assert!( - tombstone.contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad") - ); - let abort_on_top = tombstone - .lines() - .skip_while(|l| !l.contains("backtrace:")) - .skip(1) - .take_while(|l| l.starts_with(" #")) - .take(2) - .any(|f| f.contains("/system/lib/libc.so (abort")); - assert!(abort_on_top); + assert!(tombstone + .contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad")); + let abort_on_top = tombstone + .lines() + .skip_while(|l| !l.contains("backtrace:")) + .skip(1) + .take_while(|l| l.starts_with(" #")) + .take(2) + .any(|f| f.contains("/system/lib/libc.so (abort")); + assert!(abort_on_top); + } } } From a3592695ce3b414d5dd44f098ed6362af9b7271b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 14 Dec 2022 05:31:56 +0200 Subject: [PATCH 006/223] some fixes/improvements to mir::visit module --- compiler/rustc_middle/src/mir/visit.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 2ee3f551529f..0b806cdac661 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -3,15 +3,15 @@ //! ## Overview //! //! There are two visitors, one for immutable and one for mutable references, -//! but both are generated by the following macro. The code is written according -//! to the following conventions: +//! but both are generated by `make_mir_visitor` macro. +//! The code is written according to the following conventions: //! //! - introduce a `visit_foo` and a `super_foo` method for every MIR type //! - `visit_foo`, by default, calls `super_foo` //! - `super_foo`, by default, destructures the `foo` and calls `visit_foo` //! -//! This allows you as a user to override `visit_foo` for types are -//! interested in, and invoke (within that method) call +//! This allows you to override `visit_foo` for types you are +//! interested in, and invoke (within that method call) //! `self.super_foo` to get the default behavior. Just as in an OO //! language, you should never call `super` methods ordinarily except //! in that circumstance. From 76430c39f0a78448bcad5a8cdabc0d48bdf3cf2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Mart=C3=ADnez?= Date: Wed, 14 Dec 2022 19:39:16 +0100 Subject: [PATCH 007/223] Added PlayStation Vita support --- .../src/spec/armv7_sony_vita_newlibeabihf.rs | 40 ++++++ compiler/rustc_target/src/spec/mod.rs | 2 + src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 1 + .../armv7-sony-vita-eabihf.md | 127 ++++++++++++++++++ .../ui/check-cfg/well-known-values.stderr | 2 +- 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs create mode 100644 src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md diff --git a/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs new file mode 100644 index 000000000000..ebd2cca25ea9 --- /dev/null +++ b/compiler/rustc_target/src/spec/armv7_sony_vita_newlibeabihf.rs @@ -0,0 +1,40 @@ +use crate::abi::Endian; +use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions}; + +/// A base target for PlayStation Vita devices using the VITASDK toolchain (using newlib). +/// +/// Requires the VITASDK toolchain on the host system. + +pub fn target() -> Target { + let pre_link_args = TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-Wl,-q"]); + + Target { + llvm_target: "armv7a-vita-newlibeabihf".into(), + pointer_width: 32, + data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(), + arch: "arm".into(), + + options: TargetOptions { + os: "vita".into(), + endian: Endian::Little, + c_int_width: "32".into(), + dynamic_linking: false, + env: "newlib".into(), + vendor: "sony".into(), + abi: "eabihf".into(), + linker_flavor: LinkerFlavor::Gnu(Cc::Yes, Lld::No), + no_default_libraries: false, + cpu: "cortex-a9".into(), + executables: true, + families: cvs!["unix"], + linker: Some("arm-vita-eabi-gcc".into()), + relocation_model: RelocModel::Static, + features: "+v7,+neon".into(), + pre_link_args, + exe_suffix: ".elf".into(), + panic_strategy: PanicStrategy::Abort, + max_atomic_width: Some(32), + ..Default::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index be994eda14c0..a6a7009a190c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1241,6 +1241,8 @@ supported_targets! { ("aarch64-nintendo-switch-freestanding", aarch64_nintendo_switch_freestanding), + ("armv7-sony-vita-newlibeabihf", armv7_sony_vita_newlibeabihf), + ("armv7-unknown-linux-uclibceabi", armv7_unknown_linux_uclibceabi), ("armv7-unknown-linux-uclibceabihf", armv7_unknown_linux_uclibceabihf), diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 2d3b83094614..da5d9a09486e 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -22,6 +22,7 @@ - [armv4t-none-eabi](platform-support/armv4t-none-eabi.md) - [armv5te-none-eabi](platform-support/armv5te-none-eabi.md) - [armv6k-nintendo-3ds](platform-support/armv6k-nintendo-3ds.md) + - [armv7-sony-vita-newlibeabihf](platform-support/armv7-sony-vita-newlibeabihf.md) - [armv7-unknown-linux-uclibceabi](platform-support/armv7-unknown-linux-uclibceabi.md) - [armv7-unknown-linux-uclibceabihf](platform-support/armv7-unknown-linux-uclibceabihf.md) - [\*-android and \*-androideabi](platform-support/android.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d0c3ddf26062..8c710f8f6a2b 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -235,6 +235,7 @@ target | std | host | notes `armv6-unknown-netbsd-eabihf` | ? | | [`armv6k-nintendo-3ds`](platform-support/armv6k-nintendo-3ds.md) | ? | | ARMv6K Nintendo 3DS, Horizon (Requires devkitARM toolchain) `armv7-apple-ios` | ✓ | | ARMv7 iOS, Cortex-a8 +[`armv7-sony-vita-newlibeabihf`](platform-support/armv7-sony-vita-newlibeabihf.md) | ? | | ARM Cortex-A9 Sony PlayStation Vita (requires VITASDK toolchain) [`armv7-unknown-linux-uclibceabi`](platform-support/armv7-unknown-linux-uclibceabi.md) | ✓ | ✓ | ARMv7 Linux with uClibc, softfloat [`armv7-unknown-linux-uclibceabihf`](platform-support/armv7-unknown-linux-uclibceabihf.md) | ✓ | ? | ARMv7 Linux with uClibc, hardfloat `armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD diff --git a/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md b/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md new file mode 100644 index 000000000000..6619c90b849d --- /dev/null +++ b/src/doc/rustc/src/platform-support/armv7-sony-vita-eabihf.md @@ -0,0 +1,127 @@ +# armv7-sony-vita-eabihf + +**Tier: 3** + +This tier supports the ARM Cortex A9 processor running on a PlayStation Vita console. `armv7-vita-newlibeabihf` aims to have support for `std` crate using `newlib` as a bridge. + +## Designated Developers + +* [@amg98](https://github.com/amg98) + +## Requirements + +This target is cross compiled, and requires installing [VITASDK](https://vitasdk.org/) toolchain on your system. + +## Building + +You can build Rust with support for the target by adding it to the `target` +list in `config.toml`: + +```toml +[build] +build-stage = 1 +target = ["armv7-sony-vita-newlibeabihf"] +``` + +## Cross-compilation + +This target can be cross-compiled from `x86_64` on either Windows, MacOS or Linux systems. Other hosts are not supported for cross-compilation. + +## Testing + +Currently there is no support to run the rustc test suite for this target. + +## Building and Running Rust Programs + +To test your developed rust programs for PlayStation Vita, first you have to prepare a proper executable for the device using the resulting ELF file you get from compilation step. The needed steps can be automated using tools like `cargo-make`. Use the example below as a template for your project: + +```toml +[env] +TITLE = "Rust Hello World" +TITLEID = "RUST00001" +# At least a "sce_sys" folder should be place there for app metadata (title, icons, description...) +# You can find sample assets for that on $VITASDK/share/gcc-arm-vita-eabi/samples/hello_world/sce_sys/ +STATIC_DIR = "static" # Folder where static assets should be placed (sce_sys folder is at $STATIC_DIR/sce_sys) +CARGO_TARGET_DIR = { script = ["echo ${CARGO_TARGET_DIR:=target}"] } +RUST_TARGET_PATH = { script = ["echo $(pwd)"]} +RUST_TARGET = "armv7-sony-vita-newlibeabihf" +CARGO_OUT_DIR = "${CARGO_TARGET_DIR}/${RUST_TARGET}/release" + +[tasks.xbuild] +# This is the command where you get the ELF executable file (e.g. call to cargo build) + +[tasks.strip] +description = "Strip the produced ELF executable." +dependencies = ["xbuild"] +command = "arm-vita-eabi-strip" +args = ["-g", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_FS_NAME}.elf'] + +[tasks.velf] +description = "Build an VELF executable from the obtained ELF file." +dependencies = ["strip"] +command = "vita-elf-create" +args = ['${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.elf', '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf'] + +[tasks.eboot-bin] +description = "Build an `eboot.bin` file from the obtained VELF file." +dependencies = ["velf"] +command = "vita-make-fself" +args = ["-s", '${CARGO_OUT_DIR}/${CARGO_MAKE_CRATE_NAME}.velf', '${CARGO_OUT_DIR}/eboot.bin'] + +[tasks.param-sfo] +description = "Build the `param.sfo` manifest using with given TITLE and TITLEID." +command = "vita-mksfoex" +args = ["-s", 'TITLE_ID=${TITLEID}', '${TITLE}', '${CARGO_OUT_DIR}/param.sfo'] + +[tasks.manifest] +description = "List all static resources into a manifest file." +script = [ + 'mkdir -p "${CARGO_OUT_DIR}"', + ''' + if [ -d "${STATIC_DIR}" ]; then + find "${STATIC_DIR}" -type f > "${CARGO_OUT_DIR}/MANIFEST" + else + touch "${CARGO_OUT_DIR}/MANIFEST" + fi + ''' +] + +[tasks.vpk] +description = "Build a VPK distribution of the project executable and resources." +dependencies = ["eboot-bin", "param-sfo", "manifest"] +script_runner = "@rust" +script = [ + ''' + use std::io::BufRead; + use std::fs::File; + + fn main() { + + let crate_name = env!("CARGO_MAKE_CRATE_NAME"); + let static_dir = env!("STATIC_DIR"); + let out_dir = std::path::PathBuf::from(env!("CARGO_OUT_DIR")); + + let mut cmd = ::std::process::Command::new("vita-pack-vpk"); + cmd.arg("-s").arg(out_dir.join("param.sfo")); + cmd.arg("-b").arg(out_dir.join("eboot.bin")); + + // Add files from MANIFEST + if let Ok(file) = File::open(out_dir.join("MANIFEST")) { + let mut reader = ::std::io::BufReader::new(file); + let mut lines = reader.lines(); + while let Some(Ok(line)) = lines.next() { + let p1 = ::std::path::PathBuf::from(line); // path on FS + let p2 = p1.strip_prefix(static_dir).unwrap(); // path in VPK + cmd.arg("--add").arg(format!("{}={}", p1.display(), p2.display())); + } + } + + cmd.arg(out_dir.join(format!("{}.vpk", crate_name))) + .output() + .expect("command failed."); + } + ''' +] +``` + +After running the above script, you should be able to get a *.vpk file in the same folder your *.elf executable resides. Now you can pick it and install it on your own PlayStation Vita using, for example, [VitaShell](https://github.com/TheOfficialFloW/VitaShell/releases) or you can use an emulator. For the time being, the most mature emulator for PlayStation Vita is [Vita3K](https://vita3k.org/), although I personally recommend testing your programs in real hardware, as the emulator is quite experimental. diff --git a/src/test/ui/check-cfg/well-known-values.stderr b/src/test/ui/check-cfg/well-known-values.stderr index 29ececea5d39..69d799783a94 100644 --- a/src/test/ui/check-cfg/well-known-values.stderr +++ b/src/test/ui/check-cfg/well-known-values.stderr @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")] | | | help: did you mean: `"linux"` | - = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous + = note: expected values for `target_os` are: aix, android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vita, vxworks, wasi, watchos, windows, xous = note: `#[warn(unexpected_cfgs)]` on by default warning: unexpected `cfg` condition value From ca4989eac278922a64139feb6c23e5e59da4dee2 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 4 Apr 2022 16:45:09 +0400 Subject: [PATCH 008/223] SplitInternal: always set `finished` in `get_end` --- library/core/src/str/iter.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 24083ee6af44..21278c99316c 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -585,16 +585,17 @@ where impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { #[inline] fn get_end(&mut self) -> Option<&'a str> { - if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) { + if !self.finished { self.finished = true; - // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. - unsafe { - let string = self.matcher.haystack().get_unchecked(self.start..self.end); - Some(string) + + if self.allow_trailing_empty || self.end - self.start > 0 { + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. + let string = unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }; + return Some(string); } - } else { - None } + + None } #[inline] From b458a49f2664c6d8079a221f0710894d96704198 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Mon, 4 Apr 2022 17:04:58 +0400 Subject: [PATCH 009/223] Replace `Split*::as_str` with `remainder` This commit - Renames `Split*::{as_str -> remainder}` as it seems less confusing - Makes `remainder` return Option<&str> to distinguish between "iterator is exhausted" and "the tail is empty" --- library/core/src/lib.rs | 3 + library/core/src/str/iter.rs | 170 +++++++++++++++++++---------------- 2 files changed, 96 insertions(+), 77 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1823fd300627..843c5050d6a6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -158,6 +158,7 @@ #![feature(const_unsafecell_get_mut)] #![feature(const_waker)] #![feature(core_panic)] +#![feature(char_indices_offset)] #![feature(duration_consts_float)] #![feature(maybe_uninit_uninit_array)] #![feature(ptr_alignment_type)] @@ -166,6 +167,8 @@ #![feature(slice_ptr_get)] #![feature(slice_split_at_unchecked)] #![feature(str_internals)] +#![feature(str_split_remainder)] +#![feature(str_split_inclusive_remainder)] #![feature(strict_provenance)] #![feature(utf16_extra)] #![feature(utf16_extra_const)] diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index 21278c99316c..d969475aa484 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -717,14 +717,14 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { } #[inline] - fn as_str(&self) -> &'a str { + fn remainder(&self) -> Option<&'a str> { // `Self::get_end` doesn't change `self.start` if self.finished { - return ""; + return None; } // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. - unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) } + Some(unsafe { self.matcher.haystack().get_unchecked(self.start..self.end) }) } } @@ -747,44 +747,48 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> Split<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "Mary had a little lamb".split(' '); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// split.next(); - /// assert_eq!(split.as_str(), "had a little lamb"); + /// assert_eq!(split.remainder(), Some("had a little lamb")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } impl<'a, P: Pattern<'a>> RSplit<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "Mary had a little lamb".rsplit(' '); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// split.next(); - /// assert_eq!(split.as_str(), "Mary had a little"); + /// assert_eq!(split.remainder(), Some("Mary had a little")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } @@ -807,44 +811,48 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> SplitTerminator<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "A..B..".split_terminator('.'); - /// assert_eq!(split.as_str(), "A..B.."); + /// assert_eq!(split.remainder(), Some("A..B..")); /// split.next(); - /// assert_eq!(split.as_str(), ".B.."); + /// assert_eq!(split.remainder(), Some(".B..")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } impl<'a, P: Pattern<'a>> RSplitTerminator<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "A..B..".rsplit_terminator('.'); - /// assert_eq!(split.as_str(), "A..B.."); + /// assert_eq!(split.remainder(), Some("A..B..")); /// split.next(); - /// assert_eq!(split.as_str(), "A..B"); + /// assert_eq!(split.remainder(), Some("A..B")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } @@ -906,8 +914,8 @@ impl<'a, P: Pattern<'a>> SplitNInternal<'a, P> { } #[inline] - fn as_str(&self) -> &'a str { - self.iter.as_str() + fn remainder(&self) -> Option<&'a str> { + self.iter.remainder() } } @@ -930,44 +938,48 @@ generate_pattern_iterators! { } impl<'a, P: Pattern<'a>> SplitN<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "Mary had a little lamb".splitn(3, ' '); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// split.next(); - /// assert_eq!(split.as_str(), "had a little lamb"); + /// assert_eq!(split.remainder(), Some("had a little lamb")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } impl<'a, P: Pattern<'a>> RSplitN<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_as_str)] + /// #![feature(str_split_remainder)] /// let mut split = "Mary had a little lamb".rsplitn(3, ' '); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// split.next(); - /// assert_eq!(split.as_str(), "Mary had a little"); + /// assert_eq!(split.remainder(), Some("Mary had a little")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } @@ -1240,22 +1252,22 @@ impl<'a> SplitWhitespace<'a> { /// # Examples /// /// ``` - /// #![feature(str_split_whitespace_as_str)] + /// #![feature(str_split_whitespace_remainder)] /// /// let mut split = "Mary had a little lamb".split_whitespace(); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// /// split.next(); - /// assert_eq!(split.as_str(), "had a little lamb"); + /// assert_eq!(split.remainder(), Some("had a little lamb")); /// /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] #[must_use] - #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.inner.iter.as_str() + #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.inner.iter.remainder() } } @@ -1291,32 +1303,34 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { impl FusedIterator for SplitAsciiWhitespace<'_> {} impl<'a> SplitAsciiWhitespace<'a> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_whitespace_as_str)] + /// #![feature(str_split_whitespace_remainder)] /// /// let mut split = "Mary had a little lamb".split_ascii_whitespace(); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// /// split.next(); - /// assert_eq!(split.as_str(), "had a little lamb"); + /// assert_eq!(split.remainder(), Some("had a little lamb")); /// /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] #[must_use] - #[unstable(feature = "str_split_whitespace_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { + #[unstable(feature = "str_split_whitespace_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { if self.inner.iter.iter.finished { - return ""; + return None; } // SAFETY: Slice is created from str. - unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) } + Some(unsafe { crate::str::from_utf8_unchecked(&self.inner.iter.iter.v) }) } } @@ -1359,23 +1373,25 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} impl<'a, P: Pattern<'a>> SplitInclusive<'a, P> { - /// Returns remainder of the split string + /// Returns remainder of the split string. + /// + /// If the iterator is empty, returns `None`. /// /// # Examples /// /// ``` - /// #![feature(str_split_inclusive_as_str)] + /// #![feature(str_split_inclusive_remainder)] /// let mut split = "Mary had a little lamb".split_inclusive(' '); - /// assert_eq!(split.as_str(), "Mary had a little lamb"); + /// assert_eq!(split.remainder(), Some("Mary had a little lamb")); /// split.next(); - /// assert_eq!(split.as_str(), "had a little lamb"); + /// assert_eq!(split.remainder(), Some("had a little lamb")); /// split.by_ref().for_each(drop); - /// assert_eq!(split.as_str(), ""); + /// assert_eq!(split.remainder(), None); /// ``` #[inline] - #[unstable(feature = "str_split_inclusive_as_str", issue = "77998")] - pub fn as_str(&self) -> &'a str { - self.0.as_str() + #[unstable(feature = "str_split_inclusive_remainder", issue = "77998")] + pub fn remainder(&self) -> Option<&'a str> { + self.0.remainder() } } From 5a7e8f8b7970b21c40d28013800a6d4ae0c8374a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 16 Dec 2022 16:24:14 +0200 Subject: [PATCH 010/223] accept review suggestion Co-authored-by: nils <48135649+Nilstrieb@users.noreply.github.com> --- compiler/rustc_middle/src/mir/visit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0b806cdac661..1a264d2d5af9 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -3,7 +3,7 @@ //! ## Overview //! //! There are two visitors, one for immutable and one for mutable references, -//! but both are generated by `make_mir_visitor` macro. +//! but both are generated by the `make_mir_visitor` macro. //! The code is written according to the following conventions: //! //! - introduce a `visit_foo` and a `super_foo` method for every MIR type From 7df33a093c56d81f29914116df53fa0612b454eb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 17 Dec 2022 22:26:15 +0000 Subject: [PATCH 011/223] Account for RPITITs in opt_suggest_box_span --- compiler/rustc_hir_typeck/src/_match.rs | 14 ++++-- .../in-trait/box-coerce-span-in-default.rs | 49 +++++++++++++++++++ .../box-coerce-span-in-default.stderr | 11 +++++ 3 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs create mode 100644 src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index ab12cae4e2b0..7c56b8a9c7fd 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -526,7 +526,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } })?; - let opaque_ty = self.tcx.mk_opaque(rpit_def_id, substs); if !self.can_coerce(first_ty, expected) || !self.can_coerce(second_ty, expected) { return None; @@ -540,13 +539,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let pred = pred.kind().rebind(match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => { - assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty); + // FIXME(rpitit): This will need to be fixed when we move to associated types + assert!(matches!( + *trait_pred.trait_ref.self_ty().kind(), + ty::Alias(_, ty::AliasTy { def_id, substs, .. }) + if def_id == rpit_def_id && substs == substs + )); ty::PredicateKind::Clause(ty::Clause::Trait( trait_pred.with_self_ty(self.tcx, ty), )) } ty::PredicateKind::Clause(ty::Clause::Projection(mut proj_pred)) => { - assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty); + assert!(matches!( + *proj_pred.projection_ty.self_ty().kind(), + ty::Alias(_, ty::AliasTy { def_id, substs, .. }) + if def_id == rpit_def_id && substs == substs + )); proj_pred = proj_pred.with_self_ty(self.tcx, ty); ty::PredicateKind::Clause(ty::Clause::Projection(proj_pred)) } diff --git a/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs new file mode 100644 index 000000000000..a4d483dee7a5 --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.rs @@ -0,0 +1,49 @@ +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +//~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete + +struct TestA {} +struct TestB {} + +impl TestTrait for TestA { + type Output = (); +} +impl TestTrait for TestB { + type Output = (); +} + +trait TestTrait { + type Output; +} + +impl TestTrait for GreeterOutput +where + A: TestTrait, + B: TestTrait, +{ + type Output = (); +} + +enum GreeterOutput +where + A: TestTrait, + B: TestTrait, +{ + SayHello(A), + SayGoodbye(B), +} + +trait Greeter { + fn test_func(&self, func: &str) -> impl TestTrait { + match func { + "SayHello" => GreeterOutput::SayHello(TestA {}), + "SayGoodbye" => GreeterOutput::SayGoodbye(TestB {}), + _ => GreeterOutput::SayHello(TestA {}), + } + } +} + +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr new file mode 100644 index 000000000000..d681ecf25e8a --- /dev/null +++ b/src/test/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr @@ -0,0 +1,11 @@ +warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/box-coerce-span-in-default.rs:3:12 + | +LL | #![feature(return_position_impl_trait_in_trait)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + From 5cccb36cfbc887da04dc367c24d2b4947c993ff9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 18 Dec 2022 03:04:21 +0000 Subject: [PATCH 012/223] higher-ranked lifetime message --- compiler/rustc_resolve/src/late.rs | 27 ++++++++++++++----- src/test/ui/error-codes/E0637.stderr | 6 +++++ ...rrect-explicit-lifetime-name-needed.stderr | 6 +++++ ...se-inherent-impl-ampersand.rust2015.stderr | 6 +++++ ...se-inherent-impl-ampersand.rust2018.stderr | 6 +++++ ...e-clause-trait-impl-region.rust2015.stderr | 6 +++++ ...e-clause-trait-impl-region.rust2018.stderr | 6 +++++ 7 files changed, 57 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5b7a00101e9b..ef0f41223eab 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1512,7 +1512,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { count: 1, }; let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); - for rib in self.lifetime_ribs.iter().rev() { + for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { @@ -1529,16 +1529,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } else { ("`'_` cannot be used here", "`'_` is a reserved lifetime name") }; - rustc_errors::struct_span_err!( + let mut diag = rustc_errors::struct_span_err!( self.r.session, lifetime.ident.span, E0637, "{}", msg, - ) - .span_label(lifetime.ident.span, note) - .emit(); - + ); + diag.span_label(lifetime.ident.span, note); + if elided { + for rib in self.lifetime_ribs[i..].iter().rev() { + if let LifetimeRibKind::Generics { + span, + kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound, + .. + } = &rib.kind + { + diag.span_help( + *span, + "consider introducing a higher-ranked lifetime here with `for<'a>`", + ); + break; + } + } + } + diag.emit(); self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); return; } diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index 35a4b34fb0a4..78341735e191 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -21,6 +21,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: Into<&u32>, | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/E0637.rs:13:8 + | +LL | T: Into<&u32>, + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index e45387acaf31..9d859fddf56b 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | fn should_error() where T : Into<&u32> {} | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32 + | +LL | fn should_error() where T : Into<&u32> {} + | ^ error[E0106]: missing lifetime specifier --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20 diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr index fe726cb49c73..f4d14b5f87be 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr index fe726cb49c73..f4d14b5f87be 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr index fbd14de21078..63fc1a19b938 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr index fbd14de21078..63fc1a19b938 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error From 56aaf749b63824428348268dde37b84634647c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lanteri=20Thauvin?= Date: Wed, 21 Dec 2022 16:29:35 +0100 Subject: [PATCH 013/223] Test the borrowck behavior of if-let guards --- .../ui/borrowck/borrowck-drop-from-guard.rs | 9 + .../borrowck/borrowck-drop-from-guard.stderr | 21 +- .../ui/borrowck/borrowck-mutate-in-guard.rs | 19 +- .../borrowck/borrowck-mutate-in-guard.stderr | 23 ++- .../ui/borrowck/issue-31287-drop-in-guard.rs | 9 +- .../borrowck/issue-31287-drop-in-guard.stderr | 20 +- src/test/ui/issues/issue-29723.rs | 8 + src/test/ui/issues/issue-29723.stderr | 20 +- ...535-allow-mutable-borrow-in-match-guard.rs | 8 + ...issue-27282-move-match-input-into-guard.rs | 14 ++ ...e-27282-move-match-input-into-guard.stderr | 17 +- .../issue-27282-move-ref-mut-into-guard.rs | 10 + ...issue-27282-move-ref-mut-into-guard.stderr | 14 +- .../ui/nll/issue-27282-mutation-in-guard.rs | 13 ++ .../nll/issue-27282-mutation-in-guard.stderr | 14 +- .../issue-27282-reborrow-ref-mut-in-guard.rs | 14 +- ...sue-27282-reborrow-ref-mut-in-guard.stderr | 14 +- src/test/ui/nll/match-cfg-fake-edges.rs | 28 +++ src/test/ui/nll/match-cfg-fake-edges.stderr | 40 +++- src/test/ui/nll/match-guards-always-borrow.rs | 27 ++- .../ui/nll/match-guards-always-borrow.stderr | 14 +- .../ui/nll/match-guards-partially-borrow.rs | 193 ++++++++++++++++-- .../nll/match-guards-partially-borrow.stderr | 103 +++++++++- .../rfc-reject-double-move-across-arms.rs | 17 +- .../rfc-reject-double-move-across-arms.stderr | 12 +- .../rfc-reject-double-move-in-first-arm.rs | 18 +- ...rfc-reject-double-move-in-first-arm.stderr | 12 +- 27 files changed, 647 insertions(+), 64 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.rs b/src/test/ui/borrowck/borrowck-drop-from-guard.rs index 4995029a70f7..0f320af26576 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.rs +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + fn foo(_:String) {} fn main() @@ -8,4 +10,11 @@ fn main() Some(_) => {} None => { foo(my_str); } //~ ERROR [E0382] } + + let my_str = "hello".to_owned(); + match Some(42) { + Some(_) if let Some(()) = { drop(my_str); None } => {} + Some(_) => {} + None => { foo(my_str); } //~ ERROR [E0382] + } } diff --git a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr index eaf4bb38bc59..9fa28efd8554 100644 --- a/src/test/ui/borrowck/borrowck-drop-from-guard.stderr +++ b/src/test/ui/borrowck/borrowck-drop-from-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `my_str` - --> $DIR/borrowck-drop-from-guard.rs:9:23 + --> $DIR/borrowck-drop-from-guard.rs:11:23 | LL | let my_str = "hello".to_owned(); | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait @@ -15,6 +15,23 @@ help: consider cloning the value if the performance cost is acceptable LL | Some(_) if { drop(my_str.clone()); false } => {} | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `my_str` + --> $DIR/borrowck-drop-from-guard.rs:18:23 + | +LL | let my_str = "hello".to_owned(); + | ------ move occurs because `my_str` has type `String`, which does not implement the `Copy` trait +LL | match Some(42) { +LL | Some(_) if let Some(()) = { drop(my_str); None } => {} + | ------ value moved here +LL | Some(_) => {} +LL | None => { foo(my_str); } + | ^^^^^^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(my_str.clone()); None } => {} + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs index 9cbceeb945cc..d80a9e81576f 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.rs +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.rs @@ -1,9 +1,11 @@ +#![feature(if_let_guard)] + enum Enum<'a> { A(&'a isize), B(bool), } -fn foo() -> isize { +fn if_guard() -> isize { let mut n = 42; let mut x = Enum::A(&mut n); match x { @@ -16,6 +18,17 @@ fn foo() -> isize { } } -fn main() { - foo(); +fn if_let_guard() -> isize { + let mut n = 42; + let mut x = Enum::A(&mut n); + match x { + Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + //~^ ERROR cannot assign `x` in match guard + Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + //~^ ERROR cannot mutably borrow `x` in match guard + Enum::A(p) => *p, + Enum::B(_) => 2, + } } + +fn main() {} diff --git a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr index 6d05e97252d9..dbb3272fdc35 100644 --- a/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr +++ b/src/test/ui/borrowck/borrowck-mutate-in-guard.stderr @@ -1,5 +1,5 @@ error[E0510]: cannot assign `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:10:25 + --> $DIR/borrowck-mutate-in-guard.rs:12:25 | LL | match x { | - value is immutable in match guard @@ -7,7 +7,7 @@ LL | Enum::A(_) if { x = Enum::B(false); false } => 1, | ^^^^^^^^^^^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x` in match guard - --> $DIR/borrowck-mutate-in-guard.rs:12:33 + --> $DIR/borrowck-mutate-in-guard.rs:14:33 | LL | match x { | - value is immutable in match guard @@ -15,6 +15,23 @@ LL | match x { LL | Enum::A(_) if { let y = &mut x; *y = Enum::B(false); false } => 1, | ^^^^^^ cannot mutably borrow -error: aborting due to 2 previous errors +error[E0510]: cannot assign `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:25:40 + | +LL | match x { + | - value is immutable in match guard +LL | Enum::A(_) if let Some(()) = { x = Enum::B(false); None } => 1, + | ^^^^^^^^^^^^^^^^^^ cannot assign + +error[E0510]: cannot mutably borrow `x` in match guard + --> $DIR/borrowck-mutate-in-guard.rs:27:48 + | +LL | match x { + | - value is immutable in match guard +... +LL | Enum::A(_) if let Some(()) = { let y = &mut x; *y = Enum::B(false); None } => 1, + | ^^^^^^ cannot mutably borrow + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0510`. diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs index 07125b98a1f7..5b824adc6e27 100644 --- a/src/test/ui/borrowck/issue-31287-drop-in-guard.rs +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.rs @@ -1,8 +1,15 @@ +#![feature(if_let_guard)] + fn main() { let a = Some("...".to_owned()); let b = match a { Some(_) if { drop(a); false } => None, x => x, //~ ERROR use of moved value: `a` }; - println!("{:?}", b); + + let a = Some("...".to_owned()); + let b = match a { + Some(_) if let Some(()) = { drop(a); None } => None, + x => x, //~ ERROR use of moved value: `a` + }; } diff --git a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr index ad898fcabd9d..18f371c20735 100644 --- a/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr +++ b/src/test/ui/borrowck/issue-31287-drop-in-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a` - --> $DIR/issue-31287-drop-in-guard.rs:5:9 + --> $DIR/issue-31287-drop-in-guard.rs:7:9 | LL | let a = Some("...".to_owned()); | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait @@ -14,6 +14,22 @@ help: consider cloning the value if the performance cost is acceptable LL | Some(_) if { drop(a.clone()); false } => None, | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `a` + --> $DIR/issue-31287-drop-in-guard.rs:13:9 + | +LL | let a = Some("...".to_owned()); + | - move occurs because `a` has type `Option`, which does not implement the `Copy` trait +LL | let b = match a { +LL | Some(_) if let Some(()) = { drop(a); None } => None, + | - value moved here +LL | x => x, + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | Some(_) if let Some(()) = { drop(a.clone()); None } => None, + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/issues/issue-29723.rs b/src/test/ui/issues/issue-29723.rs index ce91022f093d..399e9ba0df73 100644 --- a/src/test/ui/issues/issue-29723.rs +++ b/src/test/ui/issues/issue-29723.rs @@ -1,5 +1,7 @@ // test for https://github.com/rust-lang/rust/issues/29723 +#![feature(if_let_guard)] + fn main() { let s = String::new(); let _s = match 0 { @@ -11,4 +13,10 @@ fn main() { //~^ ERROR use of moved value: `s` } }; + + let s = String::new(); + let _s = match 0 { + 0 if let Some(()) = { drop(s); None } => String::from("oops"), + _ => s //~ ERROR use of moved value: `s` + }; } diff --git a/src/test/ui/issues/issue-29723.stderr b/src/test/ui/issues/issue-29723.stderr index 92ee5cf22b71..044d8a9b5dd1 100644 --- a/src/test/ui/issues/issue-29723.stderr +++ b/src/test/ui/issues/issue-29723.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `s` - --> $DIR/issue-29723.rs:10:13 + --> $DIR/issue-29723.rs:12:13 | LL | let s = String::new(); | - move occurs because `s` has type `String`, which does not implement the `Copy` trait @@ -15,6 +15,22 @@ help: consider cloning the value if the performance cost is acceptable LL | 0 if { drop(s.clone()); false } => String::from("oops"), | ++++++++ -error: aborting due to previous error +error[E0382]: use of moved value: `s` + --> $DIR/issue-29723.rs:20:14 + | +LL | let s = String::new(); + | - move occurs because `s` has type `String`, which does not implement the `Copy` trait +LL | let _s = match 0 { +LL | 0 if let Some(()) = { drop(s); None } => String::from("oops"), + | - value moved here +LL | _ => s + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | 0 if let Some(()) = { drop(s.clone()); None } => String::from("oops"), + | ++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs index 7253d35ed2d4..ccfc8937fd72 100644 --- a/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs +++ b/src/test/ui/nll/issue-24535-allow-mutable-borrow-in-match-guard.rs @@ -5,6 +5,8 @@ // See further discussion on rust-lang/rust#24535, // rust-lang/rfcs#1006, and rust-lang/rfcs#107 +#![feature(if_let_guard)] + fn main() { rust_issue_24535(); rfcs_issue_1006_1(); @@ -23,6 +25,12 @@ fn rust_issue_24535() { 3 if compare(&a, &mut 3) => (), _ => panic!("nope"), } + + match a { + 0 => panic!("nope"), + 3 if let true = compare(&a, &mut 3) => (), + _ => panic!("nope"), + } } fn rfcs_issue_1006_1() { diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs index 4109c10e2e46..85feda5824b4 100644 --- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs +++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.rs @@ -7,6 +7,8 @@ // reaches the panic code when executed, despite the compiler warning // about that match arm being unreachable. +#![feature(if_let_guard)] + fn main() { let b = &mut true; match b { @@ -17,4 +19,16 @@ fn main() { &mut true => { println!("You might think we should get here"); }, _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } + + let b = &mut true; + match b { + //~^ ERROR use of moved value: `b` [E0382] + &mut false => {} + _ if let Some(()) = { + (|| { let bar = b; *bar = false; })(); + None + } => {} + &mut true => {} + _ => {} + } } diff --git a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr index 9be1a9279992..ae7978004576 100644 --- a/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr +++ b/src/test/ui/nll/issue-27282-move-match-input-into-guard.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `b` - --> $DIR/issue-27282-move-match-input-into-guard.rs:12:5 + --> $DIR/issue-27282-move-match-input-into-guard.rs:14:5 | LL | let b = &mut true; | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait @@ -11,6 +11,19 @@ LL | _ if { (|| { let bar = b; *bar = false; })(); | | | value moved into closure here -error: aborting due to previous error +error[E0382]: use of moved value: `b` + --> $DIR/issue-27282-move-match-input-into-guard.rs:24:5 + | +LL | let b = &mut true; + | - move occurs because `b` has type `&mut bool`, which does not implement the `Copy` trait +LL | match b { + | ^^^^^^^ value used here after move +... +LL | (|| { let bar = b; *bar = false; })(); + | -- - variable moved due to use in closure + | | + | value moved into closure here + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0382`. diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs index afa0ba780de4..833ca8afd618 100644 --- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs +++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.rs @@ -2,6 +2,8 @@ // mutable borrows in match guards by hiding the mutable borrow in a // guard behind a move (of the ref mut pattern id) within a closure. +#![feature(if_let_guard)] + fn main() { match Some(&4) { None => {}, @@ -10,4 +12,12 @@ fn main() { //~^ ERROR cannot move out of `foo` in pattern guard [E0507] Some(s) => std::process::exit(*s), } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + Some(s) => std::process::exit(*s), + } } diff --git a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr index a0d32616f83b..45119018d4e6 100644 --- a/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr +++ b/src/test/ui/nll/issue-27282-move-ref-mut-into-guard.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/issue-27282-move-ref-mut-into-guard.rs:9:19 + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:11:19 | LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | if { (|| { let bar = foo; bar.take() })(); false } => {}, | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-move-ref-mut-into-guard.rs:19:34 + | +LL | if let Some(()) = { (|| { let bar = foo; bar.take() })(); None } => {}, + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.rs b/src/test/ui/nll/issue-27282-mutation-in-guard.rs index 395c7d214d0c..4f41fc23fc34 100644 --- a/src/test/ui/nll/issue-27282-mutation-in-guard.rs +++ b/src/test/ui/nll/issue-27282-mutation-in-guard.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + fn main() { match Some(&4) { None => {}, @@ -10,4 +12,15 @@ fn main() { Some(ref _s) => println!("Note this arm is bogus; the `Some` became `None` in the guard."), _ => println!("Here is some supposedly unreachable code."), } + + match Some(&4) { + None => {}, + ref mut foo + if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard + None + } => {}, + Some(_) => {}, + } } diff --git a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr index c4ce7e62fda8..1ba696593aff 100644 --- a/src/test/ui/nll/issue-27282-mutation-in-guard.stderr +++ b/src/test/ui/nll/issue-27282-mutation-in-guard.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/issue-27282-mutation-in-guard.rs:6:18 + --> $DIR/issue-27282-mutation-in-guard.rs:8:18 | LL | (|| { let bar = foo; bar.take() })(); | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })(); | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/issue-27282-mutation-in-guard.rs:20:18 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs index 82d8b9e9ed97..ac06b2b01028 100644 --- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs +++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.rs @@ -3,7 +3,9 @@ // It reborrows instead of moving the `ref mut` pattern borrow. This // means that our conservative check for mutation in guards will // reject it. But I want to make sure that we continue to reject it -// (under NLL) even when that conservaive check goes away. +// (under NLL) even when that conservative check goes away. + +#![feature(if_let_guard)] fn main() { let mut b = &mut true; @@ -15,4 +17,14 @@ fn main() { &mut true => { println!("You might think we should get here"); }, _ => panic!("surely we could never get here, since rustc warns it is unreachable."), } + + let mut b = &mut true; + match b { + &mut false => {}, + ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + //~^ ERROR cannot borrow `r` as mutable, as it is immutable for the pattern guard + None } => { &mut *r; }, + &mut true => {}, + _ => {}, + } } diff --git a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr index 48433432de1b..5eb7a25bf9f5 100644 --- a/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/nll/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -1,5 +1,5 @@ error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard - --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:14:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | ^^ -- mutable borrow occurs due to use of `r` in closure @@ -8,6 +8,16 @@ LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); | = note: variables bound in patterns are immutable until the end of the pattern guard -error: aborting due to previous error +error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern guard + --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:24:40 + | +LL | ref mut r if let Some(()) = { (|| { let bar = &mut *r; **bar = false; })(); + | ^^ -- mutable borrow occurs due to use of `r` in closure + | | + | cannot borrow as mutable + | + = note: variables bound in patterns are immutable until the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0596`. diff --git a/src/test/ui/nll/match-cfg-fake-edges.rs b/src/test/ui/nll/match-cfg-fake-edges.rs index 252f7f8ba07c..1afc7931a6b6 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.rs +++ b/src/test/ui/nll/match-cfg-fake-edges.rs @@ -1,6 +1,8 @@ // Test that we have enough false edges to avoid exposing the exact matching // algorithm in borrow checking. +#![feature(if_let_guard)] + fn guard_always_precedes_arm(y: i32) { let mut x; // x should always be initialized, as the only way to reach the arm is @@ -9,6 +11,12 @@ fn guard_always_precedes_arm(y: i32) { 0 | 2 if { x = 2; true } => x, _ => 2, }; + + let mut x; + match y { + 0 | 2 if let Some(()) = { x = 2; Some(()) } => x, + _ => 2, + }; } fn guard_may_be_skipped(y: i32) { @@ -23,6 +31,16 @@ fn guard_may_be_skipped(y: i32) { } => 2, _ => 3, }; + + let x; + match y { + _ if let Some(()) = { x = 2; Some(()) } => 1, + _ if let Some(()) = { + x; //~ ERROR E0381 + None + } => 2, + _ => 3, + }; } fn guard_may_be_taken(y: bool) { @@ -37,6 +55,16 @@ fn guard_may_be_taken(y: bool) { } false => 3, }; + + let x = String::new(); + match y { + false if let Some(()) = { drop(x); Some(()) } => 1, + true => { + x; //~ ERROR use of moved value: `x` + 2 + } + false => 3, + }; } fn main() {} diff --git a/src/test/ui/nll/match-cfg-fake-edges.stderr b/src/test/ui/nll/match-cfg-fake-edges.stderr index f72ed3af7182..a6261345ceac 100644 --- a/src/test/ui/nll/match-cfg-fake-edges.stderr +++ b/src/test/ui/nll/match-cfg-fake-edges.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/match-cfg-fake-edges.rs:21:13 + --> $DIR/match-cfg-fake-edges.rs:29:13 | LL | let x; | - binding declared here but left uninitialized @@ -15,8 +15,25 @@ help: consider assigning a value LL | let x = 0; | +++ +error[E0381]: used binding `x` isn't initialized + --> $DIR/match-cfg-fake-edges.rs:39:13 + | +LL | let x; + | - binding declared here but left uninitialized +LL | match y { +LL | _ if let Some(()) = { x = 2; Some(()) } => 1, + | ----- binding initialized here in some conditions +LL | _ if let Some(()) = { +LL | x; + | ^ `x` used here but it isn't initialized + | +help: consider assigning a value + | +LL | let x = 0; + | +++ + error[E0382]: use of moved value: `x` - --> $DIR/match-cfg-fake-edges.rs:35:13 + --> $DIR/match-cfg-fake-edges.rs:53:13 | LL | let x = String::new(); | - move occurs because `x` has type `String`, which does not implement the `Copy` trait @@ -32,7 +49,24 @@ help: consider cloning the value if the performance cost is acceptable LL | false if { drop(x.clone()); true } => 1, | ++++++++ -error: aborting due to 2 previous errors +error[E0382]: use of moved value: `x` + --> $DIR/match-cfg-fake-edges.rs:63:13 + | +LL | let x = String::new(); + | - move occurs because `x` has type `String`, which does not implement the `Copy` trait +LL | match y { +LL | false if let Some(()) = { drop(x); Some(()) } => 1, + | - value moved here +LL | true => { +LL | x; + | ^ value used here after move + | +help: consider cloning the value if the performance cost is acceptable + | +LL | false if let Some(()) = { drop(x.clone()); Some(()) } => 1, + | ++++++++ + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0381, E0382. For more information about an error, try `rustc --explain E0381`. diff --git a/src/test/ui/nll/match-guards-always-borrow.rs b/src/test/ui/nll/match-guards-always-borrow.rs index 87dba187ba2c..ff63cc092734 100644 --- a/src/test/ui/nll/match-guards-always-borrow.rs +++ b/src/test/ui/nll/match-guards-always-borrow.rs @@ -1,3 +1,5 @@ +#![feature(if_let_guard)] + // Here is arielb1's basic example from rust-lang/rust#27282 // that AST borrowck is flummoxed by: @@ -10,6 +12,15 @@ fn should_reject_destructive_mutate_in_guard() { false } => { }, Some(s) => std::process::exit(*s), } + + match Some(&4) { + None => {}, + ref mut foo if let Some(()) = { + (|| { let bar = foo; bar.take() })(); + //~^ ERROR cannot move out of `foo` in pattern guard [E0507] + None } => { }, + Some(s) => std::process::exit(*s), + } } // Here below is a case that needs to keep working: we only use the @@ -18,7 +29,13 @@ fn should_reject_destructive_mutate_in_guard() { fn allow_mutate_in_arm_body() { match Some(&4) { None => {}, - ref mut foo if foo.is_some() && false => { foo.take(); () } + ref mut foo if foo.is_some() => { foo.take(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + ref mut foo if let Some(_) = foo => { foo.take(); () } Some(s) => std::process::exit(*s), } } @@ -29,7 +46,13 @@ fn allow_mutate_in_arm_body() { fn allow_move_into_arm_body() { match Some(&4) { None => {}, - mut foo if foo.is_some() && false => { foo.take(); () } + mut foo if foo.is_some() => { foo.unwrap(); () } + Some(s) => std::process::exit(*s), + } + + match Some(&4) { + None => {}, + mut foo if let Some(_) = foo => { foo.unwrap(); () } Some(s) => std::process::exit(*s), } } diff --git a/src/test/ui/nll/match-guards-always-borrow.stderr b/src/test/ui/nll/match-guards-always-borrow.stderr index c0fb5f65382d..fa01d3a6fd1e 100644 --- a/src/test/ui/nll/match-guards-always-borrow.stderr +++ b/src/test/ui/nll/match-guards-always-borrow.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `foo` in pattern guard - --> $DIR/match-guards-always-borrow.rs:8:14 + --> $DIR/match-guards-always-borrow.rs:10:14 | LL | (|| { let bar = foo; bar.take() })(); | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait @@ -8,6 +8,16 @@ LL | (|| { let bar = foo; bar.take() })(); | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `foo` in pattern guard + --> $DIR/match-guards-always-borrow.rs:19:14 + | +LL | (|| { let bar = foo; bar.take() })(); + | ^^ --- move occurs because `foo` has type `&mut Option<&i32>`, which does not implement the `Copy` trait + | | + | move out of `foo` occurs here + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/nll/match-guards-partially-borrow.rs b/src/test/ui/nll/match-guards-partially-borrow.rs index 81ae19ebf8a7..3a9e1654b1c2 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.rs +++ b/src/test/ui/nll/match-guards-partially-borrow.rs @@ -5,7 +5,9 @@ // Test that we don't allow mutating the value being matched on in a way that // changes which patterns it matches, until we have chosen an arm. -fn ok_mutation_in_guard(mut q: i32) { +#![feature(if_let_guard)] + +fn ok_mutation_in_if_guard(mut q: i32) { match q { // OK, mutation doesn't change which patterns g matches _ if { q = 1; false } => (), @@ -13,7 +15,15 @@ fn ok_mutation_in_guard(mut q: i32) { } } -fn ok_mutation_in_guard2(mut u: bool) { +fn ok_mutation_in_if_let_guard(mut q: i32) { + match q { + // OK, mutation doesn't change which patterns g matches + _ if let Some(()) = { q = 1; None } => (), + _ => (), + } +} + +fn ok_mutation_in_if_guard2(mut u: bool) { // OK value of u is unused before modification match u { _ => (), @@ -25,7 +35,19 @@ fn ok_mutation_in_guard2(mut u: bool) { } } -fn ok_mutation_in_guard4(mut w: (&mut bool,)) { +fn ok_mutation_in_if_let_guard2(mut u: bool) { + // OK value of u is unused before modification + match u { + _ => (), + _ if let Some(()) = { + u = true; + None + } => (), + x => (), + } +} + +fn ok_mutation_in_if_guard4(mut w: (&mut bool,)) { // OK value of u is unused before modification match w { _ => (), @@ -37,7 +59,19 @@ fn ok_mutation_in_guard4(mut w: (&mut bool,)) { } } -fn ok_indirect_mutation_in_guard(mut p: &bool) { +fn ok_mutation_in_if_let_guard4(mut w: (&mut bool,)) { + // OK value of u is unused before modification + match w { + _ => (), + _ if let Some(()) = { + *w.0 = true; + None + } => (), + x => (), + } +} + +fn ok_indirect_mutation_in_if_guard(mut p: &bool) { match *p { // OK, mutation doesn't change which patterns s matches _ if { @@ -48,7 +82,18 @@ fn ok_indirect_mutation_in_guard(mut p: &bool) { } } -fn mutation_invalidates_pattern_in_guard(mut q: bool) { +fn ok_indirect_mutation_in_if_let_guard(mut p: &bool) { + match *p { + // OK, mutation doesn't change which patterns s matches + _ if let Some(()) = { + p = &true; + None + } => (), + _ => (), + } +} + +fn mutation_invalidates_pattern_in_if_guard(mut q: bool) { match q { // q doesn't match the pattern with the guard by the end of the guard. false if { @@ -59,7 +104,18 @@ fn mutation_invalidates_pattern_in_guard(mut q: bool) { } } -fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) { +fn mutation_invalidates_pattern_in_if_let_guard(mut q: bool) { + match q { + // q doesn't match the pattern with the guard by the end of the guard. + false if let Some(()) = { + q = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn mutation_invalidates_previous_pattern_in_if_guard(mut r: bool) { match r { // r matches a previous pattern by the end of the guard. true => (), @@ -71,7 +127,19 @@ fn mutation_invalidates_previous_pattern_in_guard(mut r: bool) { } } -fn match_on_borrowed_early_end(mut s: bool) { +fn mutation_invalidates_previous_pattern_in_if_let_guard(mut r: bool) { + match r { + // r matches a previous pattern by the end of the guard. + true => (), + _ if let Some(()) = { + r = true; //~ ERROR + Some(()) + } => (), + _ => (), + } +} + +fn match_on_borrowed_early_end_if_guard(mut s: bool) { let h = &mut s; // OK value of s is unused before modification. match s { @@ -84,7 +152,20 @@ fn match_on_borrowed_early_end(mut s: bool) { } } -fn bad_mutation_in_guard(mut t: bool) { +fn match_on_borrowed_early_end_if_let_guard(mut s: bool) { + let h = &mut s; + // OK value of s is unused before modification. + match s { + _ if let Some(()) = { + *h = !*h; + None + } => (), + true => (), + false => (), + } +} + +fn bad_mutation_in_if_guard(mut t: bool) { match t { true => (), false if { @@ -95,7 +176,18 @@ fn bad_mutation_in_guard(mut t: bool) { } } -fn bad_mutation_in_guard2(mut x: Option>) { +fn bad_mutation_in_if_let_guard(mut t: bool) { + match t { + true => (), + false if let Some(()) = { + t = true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_mutation_in_if_guard2(mut x: Option>) { // Check that nested patterns are checked. match x { None => (), @@ -111,7 +203,23 @@ fn bad_mutation_in_guard2(mut x: Option>) { } } -fn bad_mutation_in_guard3(mut t: bool) { +fn bad_mutation_in_if_let_guard2(mut x: Option>) { + // Check that nested patterns are checked. + match x { + None => (), + Some(None) => (), + _ if let Some(()) = { + match x { + Some(ref mut r) => *r = None, //~ ERROR + _ => return, + }; + None + } => (), + Some(Some(r)) => println!("{}", r), + } +} + +fn bad_mutation_in_if_guard3(mut t: bool) { match t { s if { t = !t; //~ ERROR @@ -121,7 +229,17 @@ fn bad_mutation_in_guard3(mut t: bool) { } } -fn bad_indirect_mutation_in_guard(mut y: &bool) { +fn bad_mutation_in_if_let_guard3(mut t: bool) { + match t { + s if let Some(()) = { + t = !t; //~ ERROR + None + } => (), // What value should `s` have in the arm? + _ => (), + } +} + +fn bad_indirect_mutation_in_if_guard(mut y: &bool) { match *y { true => (), false if { @@ -132,7 +250,18 @@ fn bad_indirect_mutation_in_guard(mut y: &bool) { } } -fn bad_indirect_mutation_in_guard2(mut z: &bool) { +fn bad_indirect_mutation_in_if_let_guard(mut y: &bool) { + match *y { + true => (), + false if let Some(()) = { + y = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard2(mut z: &bool) { match z { &true => (), &false if { @@ -143,8 +272,19 @@ fn bad_indirect_mutation_in_guard2(mut z: &bool) { } } -fn bad_indirect_mutation_in_guard3(mut a: &bool) { - // Same as bad_indirect_mutation_in_guard2, but using match ergonomics +fn bad_indirect_mutation_in_if_let_guard2(mut z: &bool) { + match z { + &true => (), + &false if let Some(()) = { + z = &true; //~ ERROR + None + } => (), + &false => (), + } +} + +fn bad_indirect_mutation_in_if_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics match a { true => (), false if { @@ -155,7 +295,19 @@ fn bad_indirect_mutation_in_guard3(mut a: &bool) { } } -fn bad_indirect_mutation_in_guard4(mut b: &bool) { +fn bad_indirect_mutation_in_if_let_guard3(mut a: &bool) { + // Same as bad_indirect_mutation_in_if_guard2, but using match ergonomics + match a { + true => (), + false if let Some(()) = { + a = &true; //~ ERROR + None + } => (), + false => (), + } +} + +fn bad_indirect_mutation_in_if_guard4(mut b: &bool) { match b { &_ => (), &_ if { @@ -166,4 +318,15 @@ fn bad_indirect_mutation_in_guard4(mut b: &bool) { } } +fn bad_indirect_mutation_in_if_let_guard4(mut b: &bool) { + match b { + &_ => (), + &_ if let Some(()) = { + b = &true; //~ ERROR + None + } => (), + &b => (), + } +} + fn main() {} diff --git a/src/test/ui/nll/match-guards-partially-borrow.stderr b/src/test/ui/nll/match-guards-partially-borrow.stderr index 48e3a7c69931..60b8dee71a86 100644 --- a/src/test/ui/nll/match-guards-partially-borrow.stderr +++ b/src/test/ui/nll/match-guards-partially-borrow.stderr @@ -1,5 +1,14 @@ error[E0510]: cannot assign `q` in match guard - --> $DIR/match-guards-partially-borrow.rs:55:13 + --> $DIR/match-guards-partially-borrow.rs:100:13 + | +LL | match q { + | - value is immutable in match guard +... +LL | q = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `q` in match guard + --> $DIR/match-guards-partially-borrow.rs:111:13 | LL | match q { | - value is immutable in match guard @@ -8,7 +17,16 @@ LL | q = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `r` in match guard - --> $DIR/match-guards-partially-borrow.rs:67:13 + --> $DIR/match-guards-partially-borrow.rs:123:13 + | +LL | match r { + | - value is immutable in match guard +... +LL | r = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `r` in match guard + --> $DIR/match-guards-partially-borrow.rs:135:13 | LL | match r { | - value is immutable in match guard @@ -17,7 +35,16 @@ LL | r = true; | ^^^^^^^^ cannot assign error[E0510]: cannot assign `t` in match guard - --> $DIR/match-guards-partially-borrow.rs:91:13 + --> $DIR/match-guards-partially-borrow.rs:172:13 + | +LL | match t { + | - value is immutable in match guard +... +LL | t = true; + | ^^^^^^^^ cannot assign + +error[E0510]: cannot assign `t` in match guard + --> $DIR/match-guards-partially-borrow.rs:183:13 | LL | match t { | - value is immutable in match guard @@ -26,7 +53,16 @@ LL | t = true; | ^^^^^^^^ cannot assign error[E0510]: cannot mutably borrow `x.0` in match guard - --> $DIR/match-guards-partially-borrow.rs:105:22 + --> $DIR/match-guards-partially-borrow.rs:197:22 + | +LL | match x { + | - value is immutable in match guard +... +LL | Some(ref mut r) => *r = None, + | ^^^^^^^^^ cannot mutably borrow + +error[E0510]: cannot mutably borrow `x.0` in match guard + --> $DIR/match-guards-partially-borrow.rs:213:22 | LL | match x { | - value is immutable in match guard @@ -35,7 +71,7 @@ LL | Some(ref mut r) => *r = None, | ^^^^^^^^^ cannot mutably borrow error[E0506]: cannot assign to `t` because it is borrowed - --> $DIR/match-guards-partially-borrow.rs:117:13 + --> $DIR/match-guards-partially-borrow.rs:225:13 | LL | s if { | - borrow of `t` occurs here @@ -45,8 +81,28 @@ LL | false LL | } => (), // What value should `s` have in the arm? | - borrow later used here +error[E0506]: cannot assign to `t` because it is borrowed + --> $DIR/match-guards-partially-borrow.rs:235:13 + | +LL | s if let Some(()) = { + | - borrow of `t` occurs here +LL | t = !t; + | ^^^^^^ assignment to borrowed `t` occurs here +LL | None +LL | } => (), // What value should `s` have in the arm? + | - borrow later used here + error[E0510]: cannot assign `y` in match guard - --> $DIR/match-guards-partially-borrow.rs:128:13 + --> $DIR/match-guards-partially-borrow.rs:246:13 + | +LL | match *y { + | -- value is immutable in match guard +... +LL | y = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `y` in match guard + --> $DIR/match-guards-partially-borrow.rs:257:13 | LL | match *y { | -- value is immutable in match guard @@ -55,7 +111,16 @@ LL | y = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `z` in match guard - --> $DIR/match-guards-partially-borrow.rs:139:13 + --> $DIR/match-guards-partially-borrow.rs:268:13 + | +LL | match z { + | - value is immutable in match guard +... +LL | z = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `z` in match guard + --> $DIR/match-guards-partially-borrow.rs:279:13 | LL | match z { | - value is immutable in match guard @@ -64,7 +129,16 @@ LL | z = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `a` in match guard - --> $DIR/match-guards-partially-borrow.rs:151:13 + --> $DIR/match-guards-partially-borrow.rs:291:13 + | +LL | match a { + | - value is immutable in match guard +... +LL | a = &true; + | ^^^^^^^^^ cannot assign + +error[E0510]: cannot assign `a` in match guard + --> $DIR/match-guards-partially-borrow.rs:303:13 | LL | match a { | - value is immutable in match guard @@ -73,7 +147,7 @@ LL | a = &true; | ^^^^^^^^^ cannot assign error[E0510]: cannot assign `b` in match guard - --> $DIR/match-guards-partially-borrow.rs:162:13 + --> $DIR/match-guards-partially-borrow.rs:314:13 | LL | match b { | - value is immutable in match guard @@ -81,7 +155,16 @@ LL | match b { LL | b = &true; | ^^^^^^^^^ cannot assign -error: aborting due to 9 previous errors +error[E0510]: cannot assign `b` in match guard + --> $DIR/match-guards-partially-borrow.rs:325:13 + | +LL | match b { + | - value is immutable in match guard +... +LL | b = &true; + | ^^^^^^^^^ cannot assign + +error: aborting due to 18 previous errors Some errors have detailed explanations: E0506, E0510. For more information about an error, try `rustc --explain E0506`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs index d1f685f3e7a6..6f0d2b045918 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.rs @@ -1,6 +1,8 @@ +#![feature(if_let_guard)] + enum VecWrapper { A(Vec) } -fn foo(x: VecWrapper) -> usize { +fn if_guard(x: VecWrapper) -> usize { match x { VecWrapper::A(v) if { drop(v); false } => 1, //~^ ERROR cannot move out of `v` in pattern guard @@ -8,6 +10,15 @@ fn foo(x: VecWrapper) -> usize { } } -fn main() { - foo(VecWrapper::A(vec![107])); +fn if_let_guard(x: VecWrapper) -> usize { + match x { + VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + //~^ ERROR cannot move out of `v` in pattern guard + VecWrapper::A(v) => v.len() + } +} + +fn main() { + if_guard(VecWrapper::A(vec![107])); + if_let_guard(VecWrapper::A(vec![107])); } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr index 6c3d1caf8071..a749361bf30e 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-across-arms.stderr @@ -1,11 +1,19 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-across-arms.rs:5:36 + --> $DIR/rfc-reject-double-move-across-arms.rs:7:36 | LL | VecWrapper::A(v) if { drop(v); false } => 1, | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-across-arms.rs:15:51 + | +LL | VecWrapper::A(v) if let Some(()) = { drop(v); None } => 1, + | ^ move occurs because `v` has type `Vec`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs index 571f51c90012..827335f6a849 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.rs @@ -1,6 +1,8 @@ +#![feature(if_let_guard)] + struct A { a: Box } -fn foo(n: i32) { +fn if_guard(n: i32) { let x = A { a: Box::new(n) }; let _y = match x { A { a: v } if { drop(v); true } => v, @@ -9,6 +11,16 @@ fn foo(n: i32) { }; } -fn main() { - foo(107); +fn if_let_guard(n: i32) { + let x = A { a: Box::new(n) }; + let _y = match x { + A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + //~^ ERROR cannot move out of `v` in pattern guard + _ => Box::new(0), + }; +} + +fn main() { + if_guard(107); + if_let_guard(107); } diff --git a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr index d1204bc26011..9285492b2245 100644 --- a/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr +++ b/src/test/ui/rfc-0107-bind-by-move-pattern-guards/rfc-reject-double-move-in-first-arm.stderr @@ -1,11 +1,19 @@ error[E0507]: cannot move out of `v` in pattern guard - --> $DIR/rfc-reject-double-move-in-first-arm.rs:6:30 + --> $DIR/rfc-reject-double-move-in-first-arm.rs:8:30 | LL | A { a: v } if { drop(v); true } => v, | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait | = note: variables bound in patterns cannot be moved from until after the end of the pattern guard -error: aborting due to previous error +error[E0507]: cannot move out of `v` in pattern guard + --> $DIR/rfc-reject-double-move-in-first-arm.rs:17:45 + | +LL | A { a: v } if let Some(()) = { drop(v); Some(()) } => v, + | ^ move occurs because `v` has type `Box`, which does not implement the `Copy` trait + | + = note: variables bound in patterns cannot be moved from until after the end of the pattern guard + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0507`. From 22e9e52c842a1fe4e259e8ac74f0388afdc29e28 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Dec 2022 19:38:46 +0000 Subject: [PATCH 014/223] Make tests unit. --- .../mir-opt/const_allocation.main.ConstProp.after.32bit.mir | 4 ++-- .../mir-opt/const_allocation.main.ConstProp.after.64bit.mir | 4 ++-- src/test/mir-opt/const_allocation.rs | 1 + .../mir-opt/const_allocation2.main.ConstProp.after.32bit.mir | 4 ++-- .../mir-opt/const_allocation2.main.ConstProp.after.64bit.mir | 4 ++-- src/test/mir-opt/const_allocation2.rs | 1 + .../mir-opt/const_allocation3.main.ConstProp.after.32bit.mir | 4 ++-- .../mir-opt/const_allocation3.main.ConstProp.after.64bit.mir | 4 ++-- src/test/mir-opt/const_allocation3.rs | 1 + src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff | 2 +- src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff | 2 +- src/test/mir-opt/const_prop/ref_deref.rs | 1 + src/test/mir-opt/const_prop/ref_deref_project.rs | 2 +- .../mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff | 2 +- .../mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff | 2 +- src/test/mir-opt/const_prop/slice_len.rs | 1 + 16 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index da5a64cac651..6140fc52f650 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 _2 = const {alloc1: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation.rs:8:5: 8:8 + // + span: $DIR/const_allocation.rs:9:5: 9:8 // + literal: Const { ty: &&[(Option, &[&str])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index febd990681e5..b2ed23c6873c 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 _2 = const {alloc1: &&[(Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation.rs:8:5: 8:8 + // + span: $DIR/const_allocation.rs:9:5: 9:8 // + literal: Const { ty: &&[(Option, &[&str])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation.rs b/src/test/mir-opt/const_allocation.rs index b0fcb86fcee0..91a2455eb836 100644 --- a/src/test/mir-opt/const_allocation.rs +++ b/src/test/mir-opt/const_allocation.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH static FOO: &[(Option, &[&str])] = diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 389641f20f42..aab005c52d6a 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 _2 = const {alloc1: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation2.rs:5:5: 5:8 + // + span: $DIR/const_allocation2.rs:6:5: 6:8 // + literal: Const { ty: &&[(Option, &[&u8])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation2.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index ce3848e9216c..0eff9474c205 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 _2 = const {alloc1: &&[(Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation2.rs:5:5: 5:8 + // + span: $DIR/const_allocation2.rs:6:5: 6:8 // + literal: Const { ty: &&[(Option, &[&u8])], val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation2.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation2.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation2.rs b/src/test/mir-opt/const_allocation2.rs index 30afedffb39b..f2870aa47c56 100644 --- a/src/test/mir-opt/const_allocation2.rs +++ b/src/test/mir-opt/const_allocation2.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR const_allocation2.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index b72519159d75..55c6db5d0ce9 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 _2 = const {alloc1: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation3.rs:5:5: 5:8 + // + span: $DIR/const_allocation3.rs:6:5: 6:8 // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation3.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index 6bd047c7d9fb..27492a7fd22c 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -10,12 +10,12 @@ fn main() -> () { StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 _2 = const {alloc1: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 // mir::Constant - // + span: $DIR/const_allocation3.rs:5:5: 5:8 + // + span: $DIR/const_allocation3.rs:6:5: 6:8 // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc1)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:+1:5: +1:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:+1:8: +1:9 - nop; // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2 + _0 = const (); // scope 0 at $DIR/const_allocation3.rs:+0:11: +2:2 return; // scope 0 at $DIR/const_allocation3.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_allocation3.rs b/src/test/mir-opt/const_allocation3.rs index ddeb32ab9a58..da3fd089b026 100644 --- a/src/test/mir-opt/const_allocation3.rs +++ b/src/test/mir-opt/const_allocation3.rs @@ -1,3 +1,4 @@ +// unit-test: ConstProp // ignore-endian-big // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR const_allocation3.main.ConstProp.after.mir diff --git a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff index 09ce67ff15dd..8a73f0390e12 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.ConstProp.diff @@ -13,7 +13,7 @@ StorageLive(_2); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 // mir::Constant - // + span: $DIR/ref_deref.rs:5:6: 5:10 + // + span: $DIR/ref_deref.rs:6:6: 6:10 // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } _2 = _4; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 - _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 diff --git a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff index 902cd7850311..015ec4d078c1 100644 --- a/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff +++ b/src/test/mir-opt/const_prop/ref_deref.main.PromoteTemps.diff @@ -16,7 +16,7 @@ - _2 = &_3; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + _4 = const _; // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 + // mir::Constant -+ // + span: $DIR/ref_deref.rs:5:6: 5:10 ++ // + span: $DIR/ref_deref.rs:6:6: 6:10 + // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } + _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:+1:6: +1:10 _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:+1:5: +1:10 diff --git a/src/test/mir-opt/const_prop/ref_deref.rs b/src/test/mir-opt/const_prop/ref_deref.rs index 30ec9766367b..d2549c8b6aa5 100644 --- a/src/test/mir-opt/const_prop/ref_deref.rs +++ b/src/test/mir-opt/const_prop/ref_deref.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop // EMIT_MIR ref_deref.main.PromoteTemps.diff // EMIT_MIR ref_deref.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs index 659c11d9b0c2..2fdd4e153190 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.rs +++ b/src/test/mir-opt/const_prop/ref_deref_project.rs @@ -1,4 +1,4 @@ -// unit-test +// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop // EMIT_MIR ref_deref_project.main.PromoteTemps.diff // EMIT_MIR ref_deref_project.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff index 44445731e720..9017fd18e487 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff @@ -20,7 +20,7 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:5:6: 5:19 + // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff index 44445731e720..9017fd18e487 100644 --- a/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff @@ -20,7 +20,7 @@ StorageLive(_4); // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _9 = const _; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 // mir::Constant - // + span: $DIR/slice_len.rs:5:6: 5:19 + // + span: $DIR/slice_len.rs:6:6: 6:19 // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) } _4 = _9; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 _3 = _4; // scope 0 at $DIR/slice_len.rs:+1:6: +1:19 diff --git a/src/test/mir-opt/const_prop/slice_len.rs b/src/test/mir-opt/const_prop/slice_len.rs index fa9eafa8b0be..eaaf34b960eb 100644 --- a/src/test/mir-opt/const_prop/slice_len.rs +++ b/src/test/mir-opt/const_prop/slice_len.rs @@ -1,3 +1,4 @@ +// compile-flags: -Zmir-enable-passes=-SimplifyLocals-before-const-prop // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR slice_len.main.ConstProp.diff From 028b4745f4db7297c5082caabff986a477662375 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Dec 2022 19:20:55 +0000 Subject: [PATCH 015/223] Move SimplifyLocals before ConstProp. --- .../src/dead_store_elimination.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 3 +- compiler/rustc_mir_transform/src/simplify.rs | 14 +- .../const_debuginfo.main.ConstDebugInfo.diff | 90 +++++---- ...e_oob_for_slices.main.ConstProp.32bit.diff | 39 ++-- ...e_oob_for_slices.main.ConstProp.64bit.diff | 39 ++-- .../invalid_constant.main.ConstProp.diff | 16 +- .../issue_66971.main.ConstProp.diff | 3 - ...table_variable_no_prop.main.ConstProp.diff | 29 ++- ...variable_unprop_assign.main.ConstProp.diff | 47 +++-- ...es_into_variable.main.ConstProp.32bit.diff | 18 +- ...es_into_variable.main.ConstProp.64bit.diff | 18 +- ...main.SimplifyLocals-final.after.32bit.mir} | 2 +- ...main.SimplifyLocals-final.after.64bit.mir} | 2 +- .../const_prop/optimizes_into_variable.rs | 2 +- .../reify_fn_ptr.main.ConstProp.diff | 20 +- .../const_prop_miscompile.bar.ConstProp.diff | 31 ++-- ...herit_overflow.main.DataflowConstProp.diff | 31 ++-- .../issue_73223.main.SimplifyArmIdentity.diff | 173 +++++++++--------- ...76432.test.SimplifyComparisonIntegral.diff | 74 +++----- ...s.c.SimplifyLocals-before-const-prop.diff} | 4 +- ....d1.SimplifyLocals-before-const-prop.diff} | 4 +- ....d2.SimplifyLocals-before-const-prop.diff} | 4 +- ...ddr.SimplifyLocals-before-const-prop.diff} | 4 +- ...s.r.SimplifyLocals-before-const-prop.diff} | 4 +- src/test/mir-opt/simplify_locals.rs | 20 +- ....t1.SimplifyLocals-before-const-prop.diff} | 4 +- ....t2.SimplifyLocals-before-const-prop.diff} | 4 +- ....t3.SimplifyLocals-before-const-prop.diff} | 4 +- ....t4.SimplifyLocals-before-const-prop.diff} | 4 +- ..._fixedpoint.foo.SimplifyLocals-final.diff} | 4 +- .../mir-opt/simplify_locals_fixedpoint.rs | 2 +- ...ain.SimplifyLocals-before-const-prop.diff} | 4 +- .../simplify_locals_removes_unused_consts.rs | 4 +- ...map.SimplifyLocals-before-const-prop.diff} | 4 +- ...ocals_removes_unused_discriminant_reads.rs | 4 +- ...cess_never.SimplifyLocals-final.after.mir} | 2 +- ...ocess_void.SimplifyLocals-final.after.mir} | 2 +- src/test/mir-opt/uninhabited_enum.rs | 4 +- ..._let_loops.change_loop_body.ConstProp.diff | 27 +-- ...le_storage.while_loop.PreCodegen.after.mir | 6 +- src/test/ui/consts/invalid-union.32bit.stderr | 6 - src/test/ui/consts/invalid-union.64bit.stderr | 6 - 43 files changed, 348 insertions(+), 436 deletions(-) rename src/test/mir-opt/const_prop/{optimizes_into_variable.main.SimplifyLocals.after.32bit.mir => optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir} (97%) rename src/test/mir-opt/const_prop/{optimizes_into_variable.main.SimplifyLocals.after.64bit.mir => optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir} (97%) rename src/test/mir-opt/{simplify_locals.c.SimplifyLocals.diff => simplify_locals.c.SimplifyLocals-before-const-prop.diff} (94%) rename src/test/mir-opt/{simplify_locals.d1.SimplifyLocals.diff => simplify_locals.d1.SimplifyLocals-before-const-prop.diff} (87%) rename src/test/mir-opt/{simplify_locals.d2.SimplifyLocals.diff => simplify_locals.d2.SimplifyLocals-before-const-prop.diff} (94%) rename src/test/mir-opt/{simplify_locals.expose_addr.SimplifyLocals.diff => simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff} (90%) rename src/test/mir-opt/{simplify_locals.r.SimplifyLocals.diff => simplify_locals.r.SimplifyLocals-before-const-prop.diff} (93%) rename src/test/mir-opt/{simplify_locals.t1.SimplifyLocals.diff => simplify_locals.t1.SimplifyLocals-before-const-prop.diff} (90%) rename src/test/mir-opt/{simplify_locals.t2.SimplifyLocals.diff => simplify_locals.t2.SimplifyLocals-before-const-prop.diff} (90%) rename src/test/mir-opt/{simplify_locals.t3.SimplifyLocals.diff => simplify_locals.t3.SimplifyLocals-before-const-prop.diff} (92%) rename src/test/mir-opt/{simplify_locals.t4.SimplifyLocals.diff => simplify_locals.t4.SimplifyLocals-before-const-prop.diff} (90%) rename src/test/mir-opt/{simplify_locals_fixedpoint.foo.SimplifyLocals.diff => simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff} (97%) rename src/test/mir-opt/{simplify_locals_removes_unused_consts.main.SimplifyLocals.diff => simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff} (98%) rename src/test/mir-opt/{simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff => simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff} (97%) rename src/test/mir-opt/{uninhabited_enum.process_never.SimplifyLocals.after.mir => uninhabited_enum.process_never.SimplifyLocals-final.after.mir} (91%) rename src/test/mir-opt/{uninhabited_enum.process_void.SimplifyLocals.after.mir => uninhabited_enum.process_void.SimplifyLocals-final.after.mir} (93%) diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 42c580c63f06..09546330cec9 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -71,7 +71,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS bbs[block].statements[statement_index].make_nop(); } - crate::simplify::SimplifyLocals.run_pass(tcx, body) + crate::simplify::simplify_locals(body, tcx) } pub struct DeadStoreElimination; diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ae79c2290f6d..43271b013ae9 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -560,6 +560,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &multiple_return_terminators::MultipleReturnTerminators, &instcombine::InstCombine, &separate_const_switch::SeparateConstSwitch, + &simplify::SimplifyLocals::new("before-const-prop"), // // FIXME(#70073): This pass is responsible for both optimization as well as some lints. &const_prop::ConstProp, @@ -578,7 +579,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { &o1(remove_noop_landing_pads::RemoveNoopLandingPads), &o1(simplify::SimplifyCfg::new("final")), &nrvo::RenameReturnPlace, - &simplify::SimplifyLocals, + &simplify::SimplifyLocals::new("final"), &multiple_return_terminators::MultipleReturnTerminators, &deduplicate_blocks::DeduplicateBlocks, // Some cleanup necessary at least for LLVM and potentially other codegen backends. diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index 8212a7b523bb..b7aa277ae5e2 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -379,9 +379,21 @@ fn save_unreachable_coverage( )); } -pub struct SimplifyLocals; +pub struct SimplifyLocals { + label: String, +} + +impl SimplifyLocals { + pub fn new(label: &str) -> SimplifyLocals { + SimplifyLocals { label: format!("SimplifyLocals-{}", label) } + } +} impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn name(&self) -> &str { + &self.label + } + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index e959e1b2f2c3..20bad942c8d7 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -8,8 +8,8 @@ let mut _6: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:15: +4:16 let mut _7: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:19: +4:20 let mut _8: u8; // in scope 0 at $DIR/const_debuginfo.rs:+4:23: +4:24 - let mut _14: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 - let mut _15: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 + let mut _12: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:13: +13:16 + let mut _13: u32; // in scope 0 at $DIR/const_debuginfo.rs:+13:19: +13:22 scope 1 { - debug x => _1; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 + debug x => const 1_u8; // in scope 1 at $DIR/const_debuginfo.rs:+1:9: +1:10 @@ -29,23 +29,21 @@ scope 5 { - debug s => _9; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 + debug s => const "hello, world!"; // in scope 5 at $DIR/const_debuginfo.rs:+6:9: +6:10 - let _10: (bool, bool, u32); // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _16: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _17: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _18: u32; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _14: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _15: bool; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _16: u32; // in scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 scope 6 { - debug f => (bool, bool, u32){ .0 => _16, .1 => _17, .2 => _18, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 - let _11: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + debug f => (bool, bool, u32){ .0 => _14, .1 => _15, .2 => _16, }; // in scope 6 at $DIR/const_debuginfo.rs:+8:9: +8:10 + let _10: std::option::Option; // in scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 scope 7 { - debug o => _11; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 - let _12: Point; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _19: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _20: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + debug o => _10; // in scope 7 at $DIR/const_debuginfo.rs:+10:9: +10:10 + let _17: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _18: u32; // in scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 scope 8 { - debug p => Point{ .0 => _19, .1 => _20, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 - let _13: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug p => Point{ .0 => _17, .1 => _18, }; // in scope 8 at $DIR/const_debuginfo.rs:+12:9: +12:10 + let _11: u32; // in scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 scope 9 { -- debug a => _13; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 +- debug a => _11; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 + debug a => const 64_u32; // in scope 9 at $DIR/const_debuginfo.rs:+13:9: +13:10 } } @@ -83,41 +81,41 @@ // mir::Constant // + span: $DIR/const_debuginfo.rs:14:13: 14:28 // + literal: Const { ty: &str, val: Value(Slice(..)) } + StorageLive(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + StorageLive(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 StorageLive(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - StorageLive(_17); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 - StorageLive(_18); // scope 5 at $DIR/const_debuginfo.rs:+8:9: +8:10 + Deinit(_14); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + Deinit(_15); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 Deinit(_16); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - Deinit(_17); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - Deinit(_18); // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _16 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _17 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - _18 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 - StorageLive(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 - Deinit(_11); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - ((_11 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - discriminant(_11) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 - StorageLive(_19); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - StorageLive(_20); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 - Deinit(_19); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - Deinit(_20); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - _19 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - _20 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 - StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 - StorageLive(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - _14 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 - StorageLive(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _15 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 - _13 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 - StorageDead(_15); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - StorageDead(_14); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 + _14 = const true; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + _15 = const false; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + _16 = const 123_u32; // scope 5 at $DIR/const_debuginfo.rs:+8:13: +8:34 + StorageLive(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:9: +10:10 + Deinit(_10); // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + ((_10 as Some).0: u16) = const 99_u16; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + discriminant(_10) = 1; // scope 6 at $DIR/const_debuginfo.rs:+10:13: +10:24 + StorageLive(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + StorageLive(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:9: +12:10 + Deinit(_17); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + Deinit(_18); // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + _17 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + _18 = const 32_u32; // scope 7 at $DIR/const_debuginfo.rs:+12:13: +12:35 + StorageLive(_11); // scope 8 at $DIR/const_debuginfo.rs:+13:9: +13:10 + StorageLive(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 + _12 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:16 + StorageLive(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 + _13 = const 32_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:19: +13:22 + _11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 + StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 + StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 nop; // scope 0 at $DIR/const_debuginfo.rs:+0:11: +14:2 - StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_19); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_20); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_11); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_10); // scope 6 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_14); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 + StorageDead(_15); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_16); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_17); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 - StorageDead(_18); // scope 5 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_9); // scope 4 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_4); // scope 3 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_3); // scope 2 at $DIR/const_debuginfo.rs:+14:1: +14:2 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index c27b19679a83..567f6ede8bc6 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -6,17 +6,16 @@ let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 - let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _5: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + let mut _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _7: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _8: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 scope 1 { debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 scope 2 { - let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + let _4: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 scope 3 { - debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + debug _b => _4; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 } } } @@ -25,30 +24,30 @@ StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _3 = _8; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 - StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { - _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 + _4 = (*_1)[_5]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 - StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 + StorageDead(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 } diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index c27b19679a83..567f6ede8bc6 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -6,17 +6,16 @@ let _1: *const [i32]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 let mut _2: *const [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 let _3: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - let _4: [i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:26: +1:35 - let _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - let mut _7: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _8: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - let mut _9: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + let _5: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + let mut _6: usize; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _7: bool; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + let mut _8: &[i32; 3]; // in scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 scope 1 { debug a => _1; // in scope 1 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 scope 2 { - let _5: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + let _4: i32; // in scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 scope 3 { - debug _b => _5; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + debug _b => _4; // in scope 3 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 } } } @@ -25,30 +24,30 @@ StorageLive(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:9: +1:10 StorageLive(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageLive(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 - _9 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _8 = const _; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 // mir::Constant // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35 // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) } - _3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 + _3 = _8; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35 StorageDead(_2); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:34: +1:35 StorageDead(_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:35: +1:36 - StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 - StorageLive(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _6 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 - _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -- assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 -+ assert(move _8, "index out of bounds: the length is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageLive(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:13: +3:15 + StorageLive(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _5 = const 3_usize; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:23: +3:24 + _6 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- _7 = Lt(_5, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 +- assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, _5) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ _7 = Lt(const 3_usize, _6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 ++ assert(move _7, "index out of bounds: the length is {} but the index is {}", move _6, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 } bb1: { - _5 = (*_1)[_6]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 - StorageDead(_6); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 + _4 = (*_1)[_5]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 + StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 - StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 + StorageDead(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 } diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index 67a4dc3c0926..8dd0a08e319f 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -7,8 +7,6 @@ let mut _2: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:+6:34: +6:63 let mut _4: E; // in scope 0 at $DIR/invalid_constant.rs:+13:25: +13:59 let mut _5: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:+13:34: +13:55 - let mut _7: Empty; // in scope 0 at $DIR/invalid_constant.rs:+20:35: +20:73 - let mut _8: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:+20:44: +20:65 scope 1 { debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:+6:9: +6:22 let _3: [E; 1]; // in scope 1 at $DIR/invalid_constant.rs:+13:9: +13:21 @@ -17,9 +15,9 @@ let _6: [Empty; 1]; // in scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 scope 5 { debug _enum_without_variants => _6; // in scope 5 at $DIR/invalid_constant.rs:+20:9: +20:31 - let _9: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 + let _7: main::Str<"���">; // in scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 scope 7 { - debug _non_utf8_str => _9; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22 + debug _non_utf8_str => _7; // in scope 7 at $DIR/invalid_constant.rs:+24:9: +24:22 } } scope 6 { @@ -57,17 +55,11 @@ StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60 StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61 StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 - StorageLive(_7); // scope 3 at $DIR/invalid_constant.rs:+20:35: +20:73 - StorageLive(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 - Deinit(_8); // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 - (_8.0: u32) = const 0_u32; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:65 nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71 nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74 - StorageDead(_7); // scope 3 at $DIR/invalid_constant.rs:+20:73: +20:74 - StorageDead(_8); // scope 3 at $DIR/invalid_constant.rs:+20:74: +20:75 - StorageLive(_9); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 + StorageLive(_7); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2 - StorageDead(_9); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2 + StorageDead(_7); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2 StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2 StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2 StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:+27:1: +27:2 diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 7d8e647cbced..1c07d5ec0a8d 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -5,18 +5,15 @@ let mut _0: (); // return place in scope 0 at $DIR/issue_66971.rs:+0:11: +0:11 let _1: (); // in scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 let mut _2: ((), u8, u8); // in scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - let mut _3: (); // in scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 bb0: { StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - StorageLive(_3); // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 nop; // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 nop; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - StorageDead(_3); // scope 0 at $DIR/issue_66971.rs:+1:21: +1:22 _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 // mir::Constant // + span: $DIR/issue_66971.rs:17:5: 17:11 diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index eb3a7bc96d88..b34df3b877ee 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -4,39 +4,36 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +0:11 let mut _1: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 - let _2: (); // in scope 0 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 - let mut _3: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - let mut _4: *mut u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + let mut _2: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + let mut _3: *mut u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 scope 1 { debug x => _1; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 - let _5: u32; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + let _4: u32; // in scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 scope 2 { } scope 3 { - debug y => _5; // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + debug y => _4; // in scope 3 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 } } bb0: { StorageLive(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:9: +1:14 _1 = const 42_u32; // scope 0 at $DIR/mutable_variable_no_prop.rs:+1:17: +1:19 - StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 + StorageLive(_2); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - _4 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + _3 = const {alloc1: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 // mir::Constant // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19 // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) } - _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 - _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 - StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 + _2 = (*_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19 + _1 = move _2; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 + StorageDead(_2); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 nop; // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 - StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:+4:5: +4:6 - StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 - _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 + StorageLive(_4); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 + _4 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 nop; // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 - StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 + StorageDead(_4); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2 } diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 2e4b0e79e9f2..7485a0f91768 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -4,20 +4,19 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +0:11 let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + let mut _2: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 scope 1 { debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10 - let mut _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let mut _5: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 let mut _6: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let mut _7: i32; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 scope 2 { - debug x => (i32, i32){ .0 => _6, .1 => _7, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + debug x => (i32, i32){ .0 => _5, .1 => _6, }; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + let _3: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 scope 3 { - debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug y => _3; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + let _4: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 scope 4 { - debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 + debug z => _4; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 } } } @@ -32,26 +31,26 @@ } bb1: { + StorageLive(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 StorageLive(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 - StorageLive(_7); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:9: +2:14 + Deinit(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 Deinit(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - Deinit(_7); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - _6 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - _7 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 - StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - _7 = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 - StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 - StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 - _4 = _7; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 - StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 -- _5 = _6; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 -+ _5 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + _5 = const 1_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + _6 = const 2_i32; // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+2:29: +2:35 + StorageLive(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _2 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + _6 = move _2; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:5: +3:12 + StorageDead(_2); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+3:11: +3:12 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:9: +4:10 + _3 = _6; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+4:13: +4:16 + StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 +- _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 ++ _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 - StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 + StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_6); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 - StorageDead(_7); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+6:2: +6:2 } diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index 7e8ebd31ad1e..6e32c65921f2 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -9,9 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -53,16 +51,12 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index 7e8ebd31ad1e..6e32c65921f2 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -9,9 +9,7 @@ let _5: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:32: +2:33 let mut _6: usize; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 let mut _7: bool; // in scope 0 at $DIR/optimizes_into_variable.rs:+2:13: +2:34 - let mut _9: Point; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - let mut _10: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - let mut _11: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + let mut _9: u32; // in scope 0 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 scope 1 { debug x => _1; // in scope 1 at $DIR/optimizes_into_variable.rs:+1:9: +1:10 let _3: i32; // in scope 1 at $DIR/optimizes_into_variable.rs:+2:9: +2:10 @@ -53,16 +51,12 @@ StorageDead(_5); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageDead(_4); // scope 1 at $DIR/optimizes_into_variable.rs:+2:34: +2:35 StorageLive(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+3:9: +3:10 - StorageLive(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - StorageLive(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - Deinit(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _10 = const 12_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 - _11 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 -- _8 = _11; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + StorageLive(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + Deinit(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 + _9 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:36 +- _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 - StorageDead(_10); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - StorageDead(_11); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 + StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir similarity index 97% rename from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir rename to src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir index 75cea8ad2ceb..d926b9df7331 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.32bit.mir +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.32bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after SimplifyLocals +// MIR for `main` after SimplifyLocals-final fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir similarity index 97% rename from src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir rename to src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir index 75cea8ad2ceb..d926b9df7331 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals.after.64bit.mir +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.SimplifyLocals-final.after.64bit.mir @@ -1,4 +1,4 @@ -// MIR for `main` after SimplifyLocals +// MIR for `main` after SimplifyLocals-final fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +0:11 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs index 025666548180..abea07e2025b 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.rs +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs @@ -9,7 +9,7 @@ struct Point { // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR optimizes_into_variable.main.ScalarReplacementOfAggregates.diff // EMIT_MIR optimizes_into_variable.main.ConstProp.diff -// EMIT_MIR optimizes_into_variable.main.SimplifyLocals.after.mir +// EMIT_MIR optimizes_into_variable.main.SimplifyLocals-final.after.mir // EMIT_MIR optimizes_into_variable.main.PreCodegen.after.mir fn main() { let x = 2 + 2; diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff index 237a6f94aa7f..b93e9788a460 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff @@ -3,25 +3,21 @@ fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +0:11 - let mut _1: *const fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - let mut _2: usize; // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - let mut _3: fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + let mut _1: usize; // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + let mut _2: fn(); // in scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 scope 1 { } bb0: { - StorageLive(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - StorageLive(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - StorageLive(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 - _3 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + StorageLive(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + StorageLive(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 + _2 = main as fn() (Pointer(ReifyFnPointer)); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:17 // mir::Constant // + span: $DIR/reify_fn_ptr.rs:4:13: 4:17 // + literal: Const { ty: fn() {main}, val: Value() } - _2 = move _3 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 - StorageDead(_3); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 - _1 = move _2 as *const fn() (PointerFromExposedAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:41 - StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 - StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:41: +1:42 + _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 + StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 + StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 nop; // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 return; // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff index 459da2e33585..46df47440120 100644 --- a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -4,16 +4,15 @@ fn bar() -> () { let mut _0: (); // return place in scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +0:10 let mut _1: (i32,); // in scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 - let _2: (); // in scope 0 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 - let mut _3: *mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 - let mut _5: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20 + let mut _2: *mut i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 + let mut _4: i32; // in scope 0 at $DIR/const_prop_miscompile.rs:+5:13: +5:20 scope 1 { debug v => _1; // in scope 1 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 - let _4: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 + let _3: bool; // in scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 scope 2 { } scope 3 { - debug y => _4; // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 + debug y => _3; // in scope 3 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 } } @@ -21,20 +20,18 @@ StorageLive(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:9: +1:14 Deinit(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 (_1.0: i32) = const 1_i32; // scope 0 at $DIR/const_prop_miscompile.rs:+1:17: +1:21 - StorageLive(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 - StorageLive(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 - _3 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 - (*_3) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26 - StorageDead(_3); // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27 + StorageLive(_2); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 + _2 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 + (*_2) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26 + StorageDead(_2); // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27 nop; // scope 2 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 - StorageDead(_2); // scope 1 at $DIR/const_prop_miscompile.rs:+4:5: +4:6 - StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 - StorageLive(_5); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20 - _5 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18 - _4 = Eq(move _5, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25 - StorageDead(_5); // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25 + StorageLive(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 + StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20 + _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18 + _3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25 + StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25 nop; // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +6:2 - StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2 + StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+6:1: +6:2 return; // scope 0 at $DIR/const_prop_miscompile.rs:+6:2: +6:2 } diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff index bf4557ed3d92..fe5be7d8a633 100644 --- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff @@ -5,39 +5,34 @@ let mut _0: (); // return place in scope 0 at $DIR/inherit_overflow.rs:+0:11: +0:11 let mut _1: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 let mut _2: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - let mut _3: u8; // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 scope 1 { } scope 2 (inlined ::add) { // at $DIR/inherit_overflow.rs:7:13: 7:47 - debug self => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - debug other => _3; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + debug self => _1; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + debug other => _2; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + let mut _3: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL let mut _4: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - let mut _5: u8; // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - let mut _6: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + let mut _5: (u8, bool); // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL } bb0: { StorageLive(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + _1 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 StorageLive(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - _2 = const u8::MAX; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - StorageLive(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - _3 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + _2 = const 1_u8; // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageLive(_3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _3 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageLive(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - _4 = const u8::MAX; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - StorageLive(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - _5 = const 1_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - _6 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _4 = const 1_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + _5 = CheckedAdd(const u8::MAX, const 1_u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL + assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> bb1; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL } bb1: { -- _1 = move (_6.0: u8); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL -+ _1 = const 0_u8; // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - StorageDead(_5); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageDead(_4); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL - StorageDead(_3); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 + StorageDead(_3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageDead(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:47: +3:48 + StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 nop; // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2 return; // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2 } diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index 17b81633991f..a67b49ee6086 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -7,41 +7,36 @@ let mut _2: std::option::Option; // in scope 0 at $DIR/issue_73223.rs:+1:23: +1:30 let mut _3: isize; // in scope 0 at $DIR/issue_73223.rs:+2:9: +2:16 let _4: i32; // in scope 0 at $DIR/issue_73223.rs:+2:14: +2:15 - let mut _5: !; // in scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 - let mut _7: i32; // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27 - let _8: (); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _9: (&i32, &i32); // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _10: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _11: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _12: i32; // in scope 0 at $DIR/issue_73223.rs:+7:23: +7:24 - let mut _15: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _16: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _17: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _18: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _19: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _21: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _22: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _23: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _6: i32; // in scope 0 at $DIR/issue_73223.rs:+6:22: +6:27 + let mut _7: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _8: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _11: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _12: bool; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _13: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _14: i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _16: !; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _17: core::panicking::AssertKind; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _18: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _19: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _20: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _21: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _22: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _24: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL let mut _25: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _26: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _27: std::option::Option>; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _29: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _30: &i32; // in scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 1 { debug split => _1; // in scope 1 at $DIR/issue_73223.rs:+1:9: +1:14 - let _6: std::option::Option; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 + let _5: std::option::Option; // in scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 scope 3 { - debug _prev => _6; // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14 - let _13: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _14: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let mut _28: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug _prev => _5; // in scope 3 at $DIR/issue_73223.rs:+6:9: +6:14 + let _9: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _10: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let mut _23: &i32; // in scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 4 { - debug left_val => _13; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - debug right_val => _14; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - let _20: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug left_val => _9; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug right_val => _10; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + let _15: core::panicking::AssertKind; // in scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL scope 5 { - debug kind => _20; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + debug kind => _15; // in scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } } } @@ -77,70 +72,69 @@ _1 = _4; // scope 2 at $DIR/issue_73223.rs:+2:20: +2:21 StorageDead(_4); // scope 0 at $DIR/issue_73223.rs:+2:20: +2:21 StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 - StorageLive(_6); // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 - StorageLive(_7); // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 - _7 = _1; // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 - Deinit(_6); // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 - ((_6 as Some).0: i32) = move _7; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 - discriminant(_6) = 1; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 - StorageDead(_7); // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28 + StorageLive(_5); // scope 1 at $DIR/issue_73223.rs:+6:9: +6:14 + StorageLive(_6); // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 + _6 = _1; // scope 1 at $DIR/issue_73223.rs:+6:22: +6:27 + Deinit(_5); // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + ((_5 as Some).0: i32) = move _6; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + discriminant(_5) = 1; // scope 1 at $DIR/issue_73223.rs:+6:17: +6:28 + StorageDead(_6); // scope 1 at $DIR/issue_73223.rs:+6:27: +6:28 + StorageLive(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _7 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageLive(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_29); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_30); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _10 = &_1; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _28 = const _; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _23 = const _; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) } - _11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_29); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_30); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _29 = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _30 = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_11); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _13 = _29; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _14 = _30; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _17 = (*_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _18 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _16 = Eq(move _17, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_18); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_17); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _15 = Not(move _16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_16); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - switchInt(move _15) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _8 = _23; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _24 = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _25 = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_7); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _9 = _24; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _10 = _25; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _13 = (*_9); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _14 = const 1_i32; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _12 = Eq(move _13, const 1_i32); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_14); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_13); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _11 = Not(move _12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_12); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + switchInt(move _11) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL } bb4: { - StorageLive(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_20); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_20) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _22 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_15) = 0; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_16); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_17); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _17 = const core::panicking::AssertKind::Eq; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) } - StorageLive(_23); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_24); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _24 = _13; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _23 = _24; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_25); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_26); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _26 = _14; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _25 = _26; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageLive(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - Deinit(_27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - discriminant(_27) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - _21 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _23, move _25, move _27); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_19); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _19 = _9; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _18 = _19; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_20); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_21); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _21 = _10; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _20 = _21; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageLive(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + Deinit(_22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + discriminant(_22) = 0; // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + _16 = core::panicking::assert_failed::(const core::panicking::AssertKind::Eq, move _18, move _20, move _22); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL // + literal: Const { ty: for<'a, 'b, 'c> fn(core::panicking::AssertKind, &'a i32, &'b i32, Option>) -> ! {core::panicking::assert_failed::}, val: Value() } @@ -151,14 +145,13 @@ bb5: { nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_15); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_14); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_13); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_29); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_30); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - StorageDead(_8); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL + StorageDead(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL nop; // scope 0 at $DIR/issue_73223.rs:+0:11: +8:2 - StorageDead(_6); // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2 + StorageDead(_5); // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2 StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 } diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index e97b46f6ecc8..483d16775dfe 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -11,26 +11,19 @@ let mut _6: T; // in scope 0 at $DIR/issue_76432.rs:+1:21: +1:22 let mut _7: T; // in scope 0 at $DIR/issue_76432.rs:+1:24: +1:25 let mut _8: T; // in scope 0 at $DIR/issue_76432.rs:+1:27: +1:28 - let _9: [*const T; 3]; // in scope 0 at $DIR/issue_76432.rs:+2:5: +5:6 + let mut _9: usize; // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33 let mut _10: usize; // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33 - let mut _11: usize; // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33 - let mut _12: bool; // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33 - let mut _16: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:38: +3:52 - let mut _17: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:38: +3:52 - let mut _18: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:54: +3:68 - let mut _19: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:54: +3:68 - let mut _20: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84 - let mut _21: *const T; // in scope 0 at $DIR/issue_76432.rs:+3:70: +3:84 - let mut _22: !; // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL + let mut _11: bool; // in scope 0 at $DIR/issue_76432.rs:+3:9: +3:33 + let mut _15: !; // in scope 0 at $SRC_DIR/core/src/panic.rs:LL:COL scope 1 { debug v => _2; // in scope 1 at $DIR/issue_76432.rs:+1:9: +1:10 - let _13: &T; // in scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 - let _14: &T; // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 - let _15: &T; // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 + let _12: &T; // in scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 + let _13: &T; // in scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 + let _14: &T; // in scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 scope 2 { - debug v1 => _13; // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16 - debug v2 => _14; // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24 - debug v3 => _15; // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32 + debug v1 => _12; // in scope 2 at $DIR/issue_76432.rs:+3:10: +3:16 + debug v2 => _13; // in scope 2 at $DIR/issue_76432.rs:+3:18: +3:24 + debug v3 => _14; // in scope 2 at $DIR/issue_76432.rs:+3:26: +3:32 } } @@ -54,18 +47,17 @@ _2 = move _3 as &[T] (Pointer(Unsize)); // scope 0 at $DIR/issue_76432.rs:+1:19: +1:29 StorageDead(_3); // scope 0 at $DIR/issue_76432.rs:+1:28: +1:29 StorageDead(_4); // scope 0 at $DIR/issue_76432.rs:+1:29: +1:30 - StorageLive(_9); // scope 1 at $DIR/issue_76432.rs:+2:5: +5:6 - _10 = Len((*_2)); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 - _11 = const 3_usize; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 -- _12 = Eq(move _10, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 -- switchInt(move _12) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 + _9 = Len((*_2)); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 + _10 = const 3_usize; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 +- _11 = Eq(move _9, const 3_usize); // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 +- switchInt(move _11) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 + nop; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 -+ switchInt(move _10) -> [3: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 ++ switchInt(move _9) -> [3: bb2, otherwise: bb1]; // scope 1 at $DIR/issue_76432.rs:+3:9: +3:33 } bb1: { - StorageLive(_22); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL - _22 = core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL + StorageLive(_15); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL + _15 = core::panicking::panic(const "internal error: entered unreachable code"); // scope 1 at $SRC_DIR/core/src/panic.rs:LL:COL // mir::Constant // + span: $SRC_DIR/core/src/panic.rs:LL:COL // + literal: Const { ty: fn(&'static str) -> ! {core::panicking::panic}, val: Value() } @@ -75,35 +67,15 @@ } bb2: { - StorageLive(_13); // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 - _13 = &(*_2)[0 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 - StorageLive(_14); // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 - _14 = &(*_2)[1 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 - StorageLive(_15); // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 - _15 = &(*_2)[2 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 - StorageLive(_16); // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52 - StorageLive(_17); // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52 - _17 = &raw const (*_13); // scope 2 at $DIR/issue_76432.rs:+3:38: +3:40 - _16 = _17; // scope 2 at $DIR/issue_76432.rs:+3:38: +3:52 - StorageLive(_18); // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68 - StorageLive(_19); // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68 - _19 = &raw const (*_14); // scope 2 at $DIR/issue_76432.rs:+3:54: +3:56 - _18 = _19; // scope 2 at $DIR/issue_76432.rs:+3:54: +3:68 - StorageLive(_20); // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84 - StorageLive(_21); // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84 - _21 = &raw const (*_15); // scope 2 at $DIR/issue_76432.rs:+3:70: +3:72 - _20 = _21; // scope 2 at $DIR/issue_76432.rs:+3:70: +3:84 - _9 = [move _16, move _18, move _20]; // scope 2 at $DIR/issue_76432.rs:+3:37: +3:85 - StorageDead(_21); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_20); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_19); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_18); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_17); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_16); // scope 2 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_15); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 + StorageLive(_12); // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 + _12 = &(*_2)[0 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:10: +3:16 + StorageLive(_13); // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 + _13 = &(*_2)[1 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:18: +3:24 + StorageLive(_14); // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 + _14 = &(*_2)[2 of 3]; // scope 1 at $DIR/issue_76432.rs:+3:26: +3:32 StorageDead(_14); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 StorageDead(_13); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 - StorageDead(_9); // scope 1 at $DIR/issue_76432.rs:+5:6: +5:7 + StorageDead(_12); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 nop; // scope 0 at $DIR/issue_76432.rs:+0:44: +6:2 StorageDead(_5); // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2 StorageDead(_2); // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2 diff --git a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff similarity index 94% rename from src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff index 1a5143aa0fa0..1be27e96397d 100644 --- a/src/test/mir-opt/simplify_locals.c.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.c.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `c` before SimplifyLocals -+ // MIR for `c` after SimplifyLocals +- // MIR for `c` before SimplifyLocals-before-const-prop ++ // MIR for `c` after SimplifyLocals-before-const-prop fn c() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8 diff --git a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff similarity index 87% rename from src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff index 6426bf926a43..981738030186 100644 --- a/src/test/mir-opt/simplify_locals.d1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d1.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `d1` before SimplifyLocals -+ // MIR for `d1` after SimplifyLocals +- // MIR for `d1` before SimplifyLocals-before-const-prop ++ // MIR for `d1` after SimplifyLocals-before-const-prop fn d1() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 diff --git a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff similarity index 94% rename from src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff index db5ab182d6f3..b152dc8cca3a 100644 --- a/src/test/mir-opt/simplify_locals.d2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.d2.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `d2` before SimplifyLocals -+ // MIR for `d2` after SimplifyLocals +- // MIR for `d2` before SimplifyLocals-before-const-prop ++ // MIR for `d2` after SimplifyLocals-before-const-prop fn d2() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 diff --git a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff similarity index 90% rename from src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff index c707b0da07e0..9ca1dbbd071b 100644 --- a/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `expose_addr` before SimplifyLocals -+ // MIR for `expose_addr` after SimplifyLocals +- // MIR for `expose_addr` before SimplifyLocals-before-const-prop ++ // MIR for `expose_addr` after SimplifyLocals-before-const-prop fn expose_addr(_1: *const usize) -> () { debug p => _1; // in scope 0 at $DIR/simplify_locals.rs:+0:16: +0:17 diff --git a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff similarity index 93% rename from src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff index ff6eb2cff5e9..19dacb427f57 100644 --- a/src/test/mir-opt/simplify_locals.r.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.r.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `r` before SimplifyLocals -+ // MIR for `r` after SimplifyLocals +- // MIR for `r` before SimplifyLocals-before-const-prop ++ // MIR for `r` after SimplifyLocals-before-const-prop fn r() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:8: +0:8 diff --git a/src/test/mir-opt/simplify_locals.rs b/src/test/mir-opt/simplify_locals.rs index 89d9391f832d..7bbc0481c68a 100644 --- a/src/test/mir-opt/simplify_locals.rs +++ b/src/test/mir-opt/simplify_locals.rs @@ -1,4 +1,4 @@ -// unit-test: SimplifyLocals +// unit-test: SimplifyLocals-before-const-prop #![feature(thread_local)] @@ -9,26 +9,26 @@ enum E { B, } -// EMIT_MIR simplify_locals.c.SimplifyLocals.diff +// EMIT_MIR simplify_locals.c.SimplifyLocals-before-const-prop.diff fn c() { let bytes = [0u8; 10]; // Unused cast let _: &[u8] = &bytes; } -// EMIT_MIR simplify_locals.d1.SimplifyLocals.diff +// EMIT_MIR simplify_locals.d1.SimplifyLocals-before-const-prop.diff fn d1() { // Unused set discriminant let _ = E::A; } -// EMIT_MIR simplify_locals.d2.SimplifyLocals.diff +// EMIT_MIR simplify_locals.d2.SimplifyLocals-before-const-prop.diff fn d2() { // Unused set discriminant {(10, E::A)}.1 = E::B; } -// EMIT_MIR simplify_locals.r.SimplifyLocals.diff +// EMIT_MIR simplify_locals.r.SimplifyLocals-before-const-prop.diff fn r() { let mut a = 1; // Unused references @@ -38,31 +38,31 @@ fn r() { #[thread_local] static mut X: u32 = 0; -// EMIT_MIR simplify_locals.t1.SimplifyLocals.diff +// EMIT_MIR simplify_locals.t1.SimplifyLocals-before-const-prop.diff fn t1() { // Unused thread local unsafe { X }; } -// EMIT_MIR simplify_locals.t2.SimplifyLocals.diff +// EMIT_MIR simplify_locals.t2.SimplifyLocals-before-const-prop.diff fn t2() { // Unused thread local unsafe { &mut X }; } -// EMIT_MIR simplify_locals.t3.SimplifyLocals.diff +// EMIT_MIR simplify_locals.t3.SimplifyLocals-before-const-prop.diff fn t3() { // Unused thread local unsafe { *&mut X }; } -// EMIT_MIR simplify_locals.t4.SimplifyLocals.diff +// EMIT_MIR simplify_locals.t4.SimplifyLocals-before-const-prop.diff fn t4() -> u32 { // Used thread local unsafe { X + 1 } } -// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals.diff +// EMIT_MIR simplify_locals.expose_addr.SimplifyLocals-before-const-prop.diff fn expose_addr(p: *const usize) { // Used pointer to address cast. Has a side effect of exposing the provenance. p as usize; diff --git a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff similarity index 90% rename from src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff index 49db77479638..1b2e1158e45c 100644 --- a/src/test/mir-opt/simplify_locals.t1.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t1.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `t1` before SimplifyLocals -+ // MIR for `t1` after SimplifyLocals +- // MIR for `t1` before SimplifyLocals-before-const-prop ++ // MIR for `t1` after SimplifyLocals-before-const-prop fn t1() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 diff --git a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff similarity index 90% rename from src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff index e3f4ae3701b0..cf019357be77 100644 --- a/src/test/mir-opt/simplify_locals.t2.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t2.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `t2` before SimplifyLocals -+ // MIR for `t2` after SimplifyLocals +- // MIR for `t2` before SimplifyLocals-before-const-prop ++ // MIR for `t2` after SimplifyLocals-before-const-prop fn t2() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 diff --git a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff similarity index 92% rename from src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff index f1ce7778e191..90ee215808c7 100644 --- a/src/test/mir-opt/simplify_locals.t3.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t3.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `t3` before SimplifyLocals -+ // MIR for `t3` after SimplifyLocals +- // MIR for `t3` before SimplifyLocals-before-const-prop ++ // MIR for `t3` after SimplifyLocals-before-const-prop fn t3() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals.rs:+0:9: +0:9 diff --git a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff similarity index 90% rename from src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff index 71cf9594b9eb..9add9a6c5e06 100644 --- a/src/test/mir-opt/simplify_locals.t4.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals.t4.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `t4` before SimplifyLocals -+ // MIR for `t4` after SimplifyLocals +- // MIR for `t4` before SimplifyLocals-before-const-prop ++ // MIR for `t4` after SimplifyLocals-before-const-prop fn t4() -> u32 { let mut _0: u32; // return place in scope 0 at $DIR/simplify_locals.rs:+0:12: +0:15 diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff similarity index 97% rename from src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff index a2b55229303d..f888c622d908 100644 --- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff @@ -1,5 +1,5 @@ -- // MIR for `foo` before SimplifyLocals -+ // MIR for `foo` after SimplifyLocals +- // MIR for `foo` before SimplifyLocals-final ++ // MIR for `foo` after SimplifyLocals-final fn foo() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals_fixedpoint.rs:+0:13: +0:13 diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.rs b/src/test/mir-opt/simplify_locals_fixedpoint.rs index 78b1f9f55e59..1fdba6e99e3e 100644 --- a/src/test/mir-opt/simplify_locals_fixedpoint.rs +++ b/src/test/mir-opt/simplify_locals_fixedpoint.rs @@ -12,4 +12,4 @@ fn main() { foo::<()>(); } -// EMIT_MIR simplify_locals_fixedpoint.foo.SimplifyLocals.diff +// EMIT_MIR simplify_locals_fixedpoint.foo.SimplifyLocals-final.diff diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff similarity index 98% rename from src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff index 78272272b070..efb2b0961cc1 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `main` before SimplifyLocals -+ // MIR for `main` after SimplifyLocals +- // MIR for `main` before SimplifyLocals-before-const-prop ++ // MIR for `main` after SimplifyLocals-before-const-prop fn main() -> () { let mut _0: (); // return place in scope 0 at $DIR/simplify_locals_removes_unused_consts.rs:+0:11: +0:11 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_consts.rs b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs index 39b7911d4aed..7a03a2837ae7 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_consts.rs +++ b/src/test/mir-opt/simplify_locals_removes_unused_consts.rs @@ -1,4 +1,4 @@ -// unit-test: SimplifyLocals +// unit-test: SimplifyLocals-before-const-prop // compile-flags: -C overflow-checks=no fn use_zst(_: ((), ())) {} @@ -9,7 +9,7 @@ struct Temp { fn use_u8(_: u8) {} -// EMIT_MIR simplify_locals_removes_unused_consts.main.SimplifyLocals.diff +// EMIT_MIR simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff fn main() { let ((), ()) = ((), ()); use_zst(((), ())); diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff similarity index 97% rename from src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff rename to src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff index 9ec138dd82f4..027c983e6b4c 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff @@ -1,5 +1,5 @@ -- // MIR for `map` before SimplifyLocals -+ // MIR for `map` after SimplifyLocals +- // MIR for `map` before SimplifyLocals-before-const-prop ++ // MIR for `map` after SimplifyLocals-before-const-prop fn map(_1: Option>) -> Option> { debug x => _1; // in scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+0:8: +0:9 diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs index d09bd92c4e81..de65857412cf 100644 --- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs +++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.rs @@ -1,4 +1,4 @@ -// unit-test: SimplifyLocals +// unit-test: SimplifyLocals-before-const-prop fn map(x: Option>) -> Option> { match x { @@ -11,4 +11,4 @@ fn main() { map(None); } -// EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff +// EMIT_MIR simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals-before-const-prop.diff diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir similarity index 91% rename from src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir rename to src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir index 2c0fcc6621a3..b4fb330f3df2 100644 --- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals-final.after.mir @@ -1,4 +1,4 @@ -// MIR for `process_never` after SimplifyLocals +// MIR for `process_never` after SimplifyLocals-final fn process_never(_1: *const !) -> () { debug input => _1; // in scope 0 at $DIR/uninhabited_enum.rs:+0:22: +0:27 diff --git a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir similarity index 93% rename from src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir rename to src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir index ae341a7b97b6..2af864998cb0 100644 --- a/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals.after.mir +++ b/src/test/mir-opt/uninhabited_enum.process_void.SimplifyLocals-final.after.mir @@ -1,4 +1,4 @@ -// MIR for `process_void` after SimplifyLocals +// MIR for `process_void` after SimplifyLocals-final fn process_void(_1: *const Void) -> () { debug input => _1; // in scope 0 at $DIR/uninhabited_enum.rs:+0:21: +0:26 diff --git a/src/test/mir-opt/uninhabited_enum.rs b/src/test/mir-opt/uninhabited_enum.rs index 97c6e8cd5311..19db548157a6 100644 --- a/src/test/mir-opt/uninhabited_enum.rs +++ b/src/test/mir-opt/uninhabited_enum.rs @@ -2,13 +2,13 @@ pub enum Void {} -// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals.after.mir +// EMIT_MIR uninhabited_enum.process_never.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_never(input: *const !) { let _input = unsafe { &*input }; } -// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals.after.mir +// EMIT_MIR uninhabited_enum.process_void.SimplifyLocals-final.after.mir #[no_mangle] pub fn process_void(input: *const Void) { let _input = unsafe { &*input }; diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff index 984ef476e102..8d74dc84caee 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff @@ -4,13 +4,8 @@ fn change_loop_body() -> () { let mut _0: (); // return place in scope 0 at $DIR/while_let_loops.rs:+0:27: +0:27 let mut _1: i32; // in scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 - let mut _2: (); // in scope 0 at $DIR/while_let_loops.rs:+0:1: +6:2 - let mut _3: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:+2:28: +2:32 - let mut _4: isize; // in scope 0 at $DIR/while_let_loops.rs:+2:15: +2:25 - let mut _5: !; // in scope 0 at $DIR/while_let_loops.rs:+2:33: +5:6 - let mut _6: !; // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 - let _7: (); // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 - let mut _8: !; // in scope 0 at $DIR/while_let_loops.rs:+2:5: +5:6 + let mut _2: std::option::Option; // in scope 0 at $DIR/while_let_loops.rs:+2:28: +2:32 + let mut _3: isize; // in scope 0 at $DIR/while_let_loops.rs:+2:15: +2:25 scope 1 { debug _x => _1; // in scope 1 at $DIR/while_let_loops.rs:+1:9: +1:15 scope 2 { @@ -20,17 +15,17 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/while_let_loops.rs:+1:9: +1:15 _1 = const 0_i32; // scope 0 at $DIR/while_let_loops.rs:+1:18: +1:19 - StorageLive(_3); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - Deinit(_3); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 - discriminant(_3) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 -- _4 = discriminant(_3); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 -- switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 -+ _4 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 + StorageLive(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 + Deinit(_2); // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 + discriminant(_2) = 0; // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32 +- _3 = discriminant(_2); // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 +- switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 ++ _3 = const 0_isize; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 + switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 } bb1: { - switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 + switchInt(((_2 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25 } bb2: { @@ -40,14 +35,12 @@ } bb3: { - StorageLive(_7); // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6 nop; // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6 - StorageDead(_7); // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6 goto -> bb4; // scope 1 at no-location } bb4: { - StorageDead(_3); // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6 + StorageDead(_2); // scope 1 at $DIR/while_let_loops.rs:+5:5: +5:6 StorageDead(_1); // scope 0 at $DIR/while_let_loops.rs:+6:1: +6:2 return; // scope 0 at $DIR/while_let_loops.rs:+6:2: +6:2 } diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir index 1556c240dc57..b95d91b13dd7 100644 --- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir +++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir @@ -44,7 +44,7 @@ fn while_loop(_1: bool) -> () { bb5: { StorageDead(_4); // scope 0 at $DIR/while_storage.rs:+4:9: +4:10 - goto -> bb8; // scope 0 at no-location + goto -> bb7; // scope 0 at no-location } bb6: { @@ -54,10 +54,6 @@ fn while_loop(_1: bool) -> () { } bb7: { - goto -> bb8; // scope 0 at no-location - } - - bb8: { StorageDead(_2); // scope 0 at $DIR/while_storage.rs:+5:5: +5:6 return; // scope 0 at $DIR/while_storage.rs:+6:2: +6:2 } diff --git a/src/test/ui/consts/invalid-union.32bit.stderr b/src/test/ui/consts/invalid-union.32bit.stderr index 4758ea4ae881..0dd18a55786a 100644 --- a/src/test/ui/consts/invalid-union.32bit.stderr +++ b/src/test/ui/consts/invalid-union.32bit.stderr @@ -21,12 +21,6 @@ note: erroneous constant used LL | let _: &'static _ = &C; | ^^ -note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 - | -LL | let _: &'static _ = &C; - | ^^ - error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/invalid-union.64bit.stderr b/src/test/ui/consts/invalid-union.64bit.stderr index 22b85d20ce9d..07f36ee28326 100644 --- a/src/test/ui/consts/invalid-union.64bit.stderr +++ b/src/test/ui/consts/invalid-union.64bit.stderr @@ -21,12 +21,6 @@ note: erroneous constant used LL | let _: &'static _ = &C; | ^^ -note: erroneous constant used - --> $DIR/invalid-union.rs:43:25 - | -LL | let _: &'static _ = &C; - | ^^ - error: aborting due to previous error For more information about this error, try `rustc --explain E0080`. From e300abb5931156de9d8c21700df203ee7814ccd8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 4 Dec 2022 19:25:20 +0000 Subject: [PATCH 016/223] Remove Nop in simplify_locals. It's cheap and does not change anything. --- compiler/rustc_mir_transform/src/simplify.rs | 1 + src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff | 1 - .../const_prop/bad_op_mod_by_zero.main.ConstProp.diff | 1 - ...bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff | 1 - ...bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff | 1 - .../control_flow_simplification.hello.ConstProp.diff | 1 - .../const_prop/invalid_constant.main.ConstProp.diff | 3 --- .../mir-opt/const_prop/issue_66971.main.ConstProp.diff | 3 --- .../mir-opt/const_prop/issue_67019.main.ConstProp.diff | 1 - .../large_array_index.main.ConstProp.32bit.diff | 1 - .../large_array_index.main.ConstProp.64bit.diff | 1 - .../const_prop/mutable_variable.main.ConstProp.diff | 1 - .../mutable_variable_aggregate.main.ConstProp.diff | 1 - ...mutable_variable_aggregate_mut_ref.main.ConstProp.diff | 1 - ...le_variable_aggregate_partial_read.main.ConstProp.diff | 1 - .../mutable_variable_no_prop.main.ConstProp.diff | 2 -- .../mutable_variable_unprop_assign.main.ConstProp.diff | 1 - .../optimizes_into_variable.main.ConstProp.32bit.diff | 1 - .../optimizes_into_variable.main.ConstProp.64bit.diff | 1 - .../const_prop/read_immutable_static.main.ConstProp.diff | 1 - .../mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff | 1 - .../mir-opt/const_prop/repeat.main.ConstProp.32bit.diff | 1 - .../mir-opt/const_prop/repeat.main.ConstProp.64bit.diff | 1 - .../scalar_literal_propagation.main.ConstProp.diff | 1 - .../tuple_literal_propagation.main.ConstProp.diff | 1 - src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff | 2 -- src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff | 1 - .../inherit_overflow.main.DataflowConstProp.diff | 1 - .../cycle.cycle.DeadStoreElimination.diff | 8 -------- .../dead_stores_better.f.DestinationPropagation.after.mir | 1 - .../dest-prop/union.main.DestinationPropagation.diff | 3 --- .../mir-opt/issue_73223.main.SimplifyArmIdentity.diff | 3 --- .../issue_76432.test.SimplifyComparisonIntegral.diff | 1 - ...y_if.main.SimplifyConstCondition-after-const-prop.diff | 2 -- src/test/mir-opt/simplify_match.main.ConstProp.diff | 1 - .../while_let_loops.change_loop_body.ConstProp.diff | 2 -- 36 files changed, 1 insertion(+), 54 deletions(-) diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b7aa277ae5e2..8f6abe7a912f 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -569,6 +569,7 @@ fn remove_unused_definitions(used_locals: &mut UsedLocals, body: &mut Body<'_>) StatementKind::SetDiscriminant { ref place, .. } | StatementKind::Deinit(ref place) => used_locals.is_used(place.local), + StatementKind::Nop => false, _ => true, }; diff --git a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 20bad942c8d7..dd548adde7e5 100644 --- a/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/src/test/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -108,7 +108,6 @@ _11 = const 64_u32; // scope 8 at $DIR/const_debuginfo.rs:+13:13: +13:22 StorageDead(_13); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 StorageDead(_12); // scope 8 at $DIR/const_debuginfo.rs:+13:21: +13:22 - nop; // scope 0 at $DIR/const_debuginfo.rs:+0:11: +14:2 StorageDead(_11); // scope 8 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_17); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 StorageDead(_18); // scope 7 at $DIR/const_debuginfo.rs:+14:1: +14:2 diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff index 22151304259b..8485703e39f2 100644 --- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero.main.ConstProp.diff @@ -45,7 +45,6 @@ - _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 + _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:14: +2:19 StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+2:18: +2:19 - nop; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+0:11: +3:2 StorageDead(_2); // scope 1 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 StorageDead(_1); // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:1: +3:2 return; // scope 0 at $DIR/bad_op_mod_by_zero.rs:+3:2: +3:2 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff index 567f6ede8bc6..27e41d4869d7 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff @@ -46,7 +46,6 @@ bb1: { _4 = (*_1)[_5]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 StorageDead(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff index 567f6ede8bc6..27e41d4869d7 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff @@ -46,7 +46,6 @@ bb1: { _4 = (*_1)[_5]; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:18: +3:25 StorageDead(_5); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+3:25: +3:26 - nop; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+2:5: +4:6 StorageDead(_4); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:+4:5: +4:6 StorageDead(_1); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:1: +5:2 return; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff index 147670f8a915..f270ab8b69f0 100644 --- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff +++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff @@ -25,7 +25,6 @@ } bb2: { - nop; // scope 0 at $DIR/control_flow_simplification.rs:+3:6: +3:6 StorageDead(_1); // scope 0 at $DIR/control_flow_simplification.rs:+3:5: +3:6 return; // scope 0 at $DIR/control_flow_simplification.rs:+4:2: +4:2 } diff --git a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff index 8dd0a08e319f..6c4757c1a810 100644 --- a/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff @@ -55,10 +55,7 @@ StorageDead(_4); // scope 1 at $DIR/invalid_constant.rs:+13:59: +13:60 StorageDead(_5); // scope 1 at $DIR/invalid_constant.rs:+13:60: +13:61 StorageLive(_6); // scope 3 at $DIR/invalid_constant.rs:+20:9: +20:31 - nop; // scope 6 at $DIR/invalid_constant.rs:+20:44: +20:71 - nop; // scope 3 at $DIR/invalid_constant.rs:+20:34: +20:74 StorageLive(_7); // scope 5 at $DIR/invalid_constant.rs:+24:9: +24:22 - nop; // scope 0 at $DIR/invalid_constant.rs:+0:11: +27:2 StorageDead(_7); // scope 5 at $DIR/invalid_constant.rs:+27:1: +27:2 StorageDead(_6); // scope 3 at $DIR/invalid_constant.rs:+27:1: +27:2 StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:+27:1: +27:2 diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff index 1c07d5ec0a8d..488e772d0ea8 100644 --- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff @@ -9,9 +9,7 @@ bb0: { StorageLive(_1); // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 StorageLive(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - nop; // scope 0 at $DIR/issue_66971.rs:+1:13: +1:15 Deinit(_2); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 - nop; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 (_2.1: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 (_2.2: u8) = const 0_u8; // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22 _1 = encode(move _2) -> bb1; // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23 @@ -23,7 +21,6 @@ bb1: { StorageDead(_2); // scope 0 at $DIR/issue_66971.rs:+1:22: +1:23 StorageDead(_1); // scope 0 at $DIR/issue_66971.rs:+1:23: +1:24 - nop; // scope 0 at $DIR/issue_66971.rs:+0:11: +2:2 return; // scope 0 at $DIR/issue_66971.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff index 79cd8bf48396..cd53048597b8 100644 --- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff @@ -27,7 +27,6 @@ bb1: { StorageDead(_2); // scope 0 at $DIR/issue_67019.rs:+1:19: +1:20 StorageDead(_1); // scope 0 at $DIR/issue_67019.rs:+1:20: +1:21 - nop; // scope 0 at $DIR/issue_67019.rs:+0:11: +2:2 return; // scope 0 at $DIR/issue_67019.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff index 96de39258e4d..5331e5b82122 100644 --- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.32bit.diff @@ -29,7 +29,6 @@ _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 } diff --git a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff index 96de39258e4d..5331e5b82122 100644 --- a/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/large_array_index.main.ConstProp.64bit.diff @@ -29,7 +29,6 @@ _1 = _2[_3]; // scope 0 at $DIR/large_array_index.rs:+2:17: +2:32 StorageDead(_3); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 StorageDead(_2); // scope 0 at $DIR/large_array_index.rs:+2:32: +2:33 - nop; // scope 0 at $DIR/large_array_index.rs:+0:11: +3:2 StorageDead(_1); // scope 0 at $DIR/large_array_index.rs:+3:1: +3:2 return; // scope 0 at $DIR/large_array_index.rs:+3:2: +3:2 } diff --git a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff index 3bbd6a87f971..a672c457a72b 100644 --- a/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable.main.ConstProp.diff @@ -19,7 +19,6 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:+3:9: +3:10 - _2 = _1; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable.rs:+3:13: +3:14 - nop; // scope 0 at $DIR/mutable_variable.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff index fed6a98b9f36..f6bf522065ba 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.main.ConstProp.diff @@ -21,7 +21,6 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:9: +3:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 + _2 = const (42_i32, 99_i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:+3:13: +3:14 - nop; // scope 0 at $DIR/mutable_variable_aggregate.rs:+0:11: +4:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:1: +4:2 return; // scope 0 at $DIR/mutable_variable_aggregate.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff index 90eebd8feac6..213a70227d87 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.main.ConstProp.diff @@ -26,7 +26,6 @@ ((*_2).1: i32) = const 99_i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+3:5: +3:13 StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:9: +4:10 _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+4:13: +4:14 - nop; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+0:11: +5:2 StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:+5:1: +5:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff index 6eda503c1eec..149aa6290d0e 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff @@ -26,7 +26,6 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:9: +4:10 - _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 + _2 = const 99_i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+4:13: +4:16 - nop; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+0:11: +5:2 StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:1: +5:2 return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+5:2: +5:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff index b34df3b877ee..b9d551c5e5fc 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff @@ -29,10 +29,8 @@ _1 = move _2; // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19 StorageDead(_2); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:18: +3:19 StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:19: +3:20 - nop; // scope 2 at $DIR/mutable_variable_no_prop.rs:+2:5: +4:6 StorageLive(_4); // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:9: +5:10 _4 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:+5:13: +5:14 - nop; // scope 0 at $DIR/mutable_variable_no_prop.rs:+0:11: +6:2 StorageDead(_4); // scope 1 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:1: +6:2 return; // scope 0 at $DIR/mutable_variable_no_prop.rs:+6:2: +6:2 diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff index 7485a0f91768..c3f77b960a2d 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff @@ -46,7 +46,6 @@ StorageLive(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:9: +5:10 - _4 = _5; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 + _4 = const 1_i32; // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+5:13: +5:16 - nop; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+0:11: +6:2 StorageDead(_4); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 StorageDead(_5); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:+6:1: +6:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff index 6e32c65921f2..7c7aeac4c451 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.32bit.diff @@ -57,7 +57,6 @@ - _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff index 6e32c65921f2..7c7aeac4c451 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable.main.ConstProp.64bit.diff @@ -57,7 +57,6 @@ - _8 = _9; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 + _8 = const 42_u32; // scope 2 at $DIR/optimizes_into_variable.rs:+3:13: +3:38 StorageDead(_9); // scope 2 at $DIR/optimizes_into_variable.rs:+3:38: +3:39 - nop; // scope 0 at $DIR/optimizes_into_variable.rs:+0:11: +4:2 StorageDead(_8); // scope 2 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_3); // scope 1 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/optimizes_into_variable.rs:+4:1: +4:2 diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff index b9c283a54821..388c6ca810b6 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff @@ -36,7 +36,6 @@ StorageDead(_2); // scope 0 at $DIR/read_immutable_static.rs:+1:21: +1:22 StorageDead(_5); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 StorageDead(_3); // scope 0 at $DIR/read_immutable_static.rs:+1:22: +1:23 - nop; // scope 0 at $DIR/read_immutable_static.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/read_immutable_static.rs:+2:1: +2:2 return; // scope 0 at $DIR/read_immutable_static.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff index b93e9788a460..15c93f270d70 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.main.ConstProp.diff @@ -18,7 +18,6 @@ _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/reify_fn_ptr.rs:+1:13: +1:26 StorageDead(_2); // scope 0 at $DIR/reify_fn_ptr.rs:+1:25: +1:26 StorageDead(_1); // scope 0 at $DIR/reify_fn_ptr.rs:+1:40: +1:41 - nop; // scope 0 at $DIR/reify_fn_ptr.rs:+0:11: +2:2 return; // scope 0 at $DIR/reify_fn_ptr.rs:+2:2: +2:2 } } diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff index 7c4977996917..636032adb819 100644 --- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff +++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.32bit.diff @@ -35,7 +35,6 @@ StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff index 7c4977996917..636032adb819 100644 --- a/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff +++ b/src/test/mir-opt/const_prop/repeat.main.ConstProp.64bit.diff @@ -35,7 +35,6 @@ StorageDead(_2); // scope 0 at $DIR/repeat.rs:+1:31: +1:32 StorageDead(_4); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 StorageDead(_3); // scope 0 at $DIR/repeat.rs:+1:32: +1:33 - nop; // scope 0 at $DIR/repeat.rs:+0:11: +2:2 StorageDead(_1); // scope 0 at $DIR/repeat.rs:+2:1: +2:2 return; // scope 0 at $DIR/repeat.rs:+2:2: +2:2 } diff --git a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff index 5920937e0fd4..d518eff04eba 100644 --- a/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff @@ -27,7 +27,6 @@ bb1: { StorageDead(_3); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:14: +2:15 StorageDead(_2); // scope 1 at $DIR/scalar_literal_propagation.rs:+2:15: +2:16 - nop; // scope 0 at $DIR/scalar_literal_propagation.rs:+0:11: +3:2 StorageDead(_1); // scope 0 at $DIR/scalar_literal_propagation.rs:+3:1: +3:2 return; // scope 0 at $DIR/scalar_literal_propagation.rs:+3:2: +3:2 } diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff index a0603c60dc79..e4c92b617c6a 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff @@ -28,7 +28,6 @@ bb1: { StorageDead(_3); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:14: +3:15 StorageDead(_2); // scope 1 at $DIR/tuple_literal_propagation.rs:+3:15: +3:16 - nop; // scope 0 at $DIR/tuple_literal_propagation.rs:+0:11: +4:2 StorageDead(_1); // scope 0 at $DIR/tuple_literal_propagation.rs:+4:1: +4:2 return; // scope 0 at $DIR/tuple_literal_propagation.rs:+4:2: +4:2 } diff --git a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff index 46df47440120..ea9fec0aa15d 100644 --- a/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.bar.ConstProp.diff @@ -24,13 +24,11 @@ _2 = &raw mut (_1.0: i32); // scope 2 at $DIR/const_prop_miscompile.rs:+3:10: +3:22 (*_2) = const 5_i32; // scope 2 at $DIR/const_prop_miscompile.rs:+3:9: +3:26 StorageDead(_2); // scope 2 at $DIR/const_prop_miscompile.rs:+3:26: +3:27 - nop; // scope 2 at $DIR/const_prop_miscompile.rs:+2:5: +4:6 StorageLive(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+5:9: +5:10 StorageLive(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:20 _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:15: +5:18 _3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+5:13: +5:25 StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+5:24: +5:25 - nop; // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +6:2 StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+6:1: +6:2 StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+6:1: +6:2 return; // scope 0 at $DIR/const_prop_miscompile.rs:+6:2: +6:2 diff --git a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff index e8bd98cf8cba..043f40474171 100644 --- a/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff +++ b/src/test/mir-opt/const_prop_miscompile.foo.ConstProp.diff @@ -27,7 +27,6 @@ _4 = (_1.0: i32); // scope 1 at $DIR/const_prop_miscompile.rs:+3:15: +3:18 _3 = Eq(move _4, const 5_i32); // scope 1 at $DIR/const_prop_miscompile.rs:+3:13: +3:25 StorageDead(_4); // scope 1 at $DIR/const_prop_miscompile.rs:+3:24: +3:25 - nop; // scope 0 at $DIR/const_prop_miscompile.rs:+0:10: +4:2 StorageDead(_3); // scope 1 at $DIR/const_prop_miscompile.rs:+4:1: +4:2 StorageDead(_1); // scope 0 at $DIR/const_prop_miscompile.rs:+4:1: +4:2 return; // scope 0 at $DIR/const_prop_miscompile.rs:+4:2: +4:2 diff --git a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff index fe5be7d8a633..02aafd7acc4c 100644 --- a/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff +++ b/src/test/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff @@ -33,7 +33,6 @@ StorageDead(_3); // scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL StorageDead(_2); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 StorageDead(_1); // scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47 - nop; // scope 0 at $DIR/inherit_overflow.rs:+0:11: +4:2 return; // scope 0 at $DIR/inherit_overflow.rs:+4:2: +4:2 } } diff --git a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff index 80f8905adc92..cd3b792fb751 100644 --- a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff +++ b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff @@ -59,14 +59,6 @@ - _4 = const (); // scope 0 at $DIR/cycle.rs:+3:18: +8:6 - StorageDead(_6); // scope 0 at $DIR/cycle.rs:+8:5: +8:6 + StorageLive(_5); // scope 0 at $DIR/cycle.rs:+4:13: +4:17 -+ nop; // scope 0 at $DIR/cycle.rs:+4:20: +4:21 -+ nop; // scope 1 at $DIR/cycle.rs:+5:13: +5:14 -+ nop; // scope 1 at $DIR/cycle.rs:+5:9: +5:14 -+ nop; // scope 1 at $DIR/cycle.rs:+6:13: +6:14 -+ nop; // scope 1 at $DIR/cycle.rs:+6:9: +6:14 -+ nop; // scope 1 at $DIR/cycle.rs:+7:13: +7:17 -+ nop; // scope 1 at $DIR/cycle.rs:+7:9: +7:17 -+ nop; // scope 0 at $DIR/cycle.rs:+3:18: +8:6 StorageDead(_5); // scope 0 at $DIR/cycle.rs:+8:5: +8:6 + StorageDead(_4); // scope 0 at $DIR/cycle.rs:+8:5: +8:6 goto -> bb1; // scope 0 at $DIR/cycle.rs:+3:5: +8:6 diff --git a/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir index ba7f76d2841f..26068931aaf2 100644 --- a/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir +++ b/src/test/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir @@ -13,7 +13,6 @@ fn f(_1: usize) -> usize { bb0: { nop; // scope 0 at $DIR/dead_stores_better.rs:+1:9: +1:10 nop; // scope 0 at $DIR/dead_stores_better.rs:+1:13: +1:14 - nop; // scope 1 at $DIR/dead_stores_better.rs:+2:5: +2:10 nop; // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10 nop; // scope 1 at $DIR/dead_stores_better.rs:+3:9: +3:10 nop; // scope 1 at $DIR/dead_stores_better.rs:+3:5: +3:10 diff --git a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff index 85d994bc8b97..fbed3178801f 100644 --- a/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff +++ b/src/test/mir-opt/dest-prop/union.main.DestinationPropagation.diff @@ -25,11 +25,8 @@ } bb1: { - nop; // scope 0 at $DIR/union.rs:+5:14: +5:30 - nop; // scope 0 at $DIR/union.rs:+5:14: +5:30 StorageDead(_2); // scope 0 at $DIR/union.rs:+5:29: +5:30 StorageLive(_3); // scope 1 at $DIR/union.rs:+7:10: +7:26 - nop; // scope 2 at $DIR/union.rs:+7:19: +7:24 StorageDead(_3); // scope 1 at $DIR/union.rs:+7:26: +7:27 StorageDead(_1); // scope 0 at $DIR/union.rs:+8:1: +8:2 return; // scope 0 at $DIR/union.rs:+8:2: +8:2 diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff index a67b49ee6086..bf3bcfdb5944 100644 --- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff @@ -56,7 +56,6 @@ } bb1: { - nop; // scope 0 at $DIR/issue_73223.rs:+3:17: +3:23 StorageDead(_2); // scope 0 at $DIR/issue_73223.rs:+4:6: +4:7 StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 @@ -144,13 +143,11 @@ } bb5: { - nop; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_11); // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_10); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_9); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_24); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL StorageDead(_25); // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL - nop; // scope 0 at $DIR/issue_73223.rs:+0:11: +8:2 StorageDead(_5); // scope 1 at $DIR/issue_73223.rs:+8:1: +8:2 StorageDead(_1); // scope 0 at $DIR/issue_73223.rs:+8:1: +8:2 return; // scope 0 at $DIR/issue_73223.rs:+8:2: +8:2 diff --git a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff index 483d16775dfe..c24543daeacb 100644 --- a/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff +++ b/src/test/mir-opt/issue_76432.test.SimplifyComparisonIntegral.diff @@ -76,7 +76,6 @@ StorageDead(_14); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 StorageDead(_13); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 StorageDead(_12); // scope 1 at $DIR/issue_76432.rs:+3:84: +3:85 - nop; // scope 0 at $DIR/issue_76432.rs:+0:44: +6:2 StorageDead(_5); // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2 StorageDead(_2); // scope 0 at $DIR/issue_76432.rs:+6:1: +6:2 return; // scope 0 at $DIR/issue_76432.rs:+6:2: +6:2 diff --git a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff index aea011474435..f9e22866bee9 100644 --- a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff +++ b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff @@ -23,12 +23,10 @@ bb2: { StorageDead(_2); // scope 0 at $DIR/simplify_if.rs:+2:15: +2:16 - nop; // scope 0 at $DIR/simplify_if.rs:+1:14: +3:6 goto -> bb4; // scope 0 at $DIR/simplify_if.rs:+1:5: +3:6 } bb3: { - nop; // scope 0 at $DIR/simplify_if.rs:+3:6: +3:6 goto -> bb4; // scope 0 at $DIR/simplify_if.rs:+1:5: +3:6 } diff --git a/src/test/mir-opt/simplify_match.main.ConstProp.diff b/src/test/mir-opt/simplify_match.main.ConstProp.diff index f00ac5716a75..70bfbf1b3e36 100644 --- a/src/test/mir-opt/simplify_match.main.ConstProp.diff +++ b/src/test/mir-opt/simplify_match.main.ConstProp.diff @@ -21,7 +21,6 @@ } bb1: { - nop; // scope 0 at $DIR/simplify_match.rs:+3:18: +3:20 goto -> bb3; // scope 0 at $DIR/simplify_match.rs:+3:18: +3:20 } diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff index 8d74dc84caee..bb1de59d4a73 100644 --- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff +++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff @@ -30,12 +30,10 @@ bb2: { _1 = const 1_i32; // scope 2 at $DIR/while_let_loops.rs:+3:9: +3:15 - nop; // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14 goto -> bb4; // scope 2 at $DIR/while_let_loops.rs:+4:9: +4:14 } bb3: { - nop; // scope 1 at $DIR/while_let_loops.rs:+2:5: +5:6 goto -> bb4; // scope 1 at no-location } From b8ec86cabb10866b3c33c6e275b13e3709168ce8 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 6 Dec 2022 18:58:05 +0000 Subject: [PATCH 017/223] Adapt codegen test. --- src/test/codegen/zst-offset.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/codegen/zst-offset.rs b/src/test/codegen/zst-offset.rs index 29d2a1754a3a..844d5870a846 100644 --- a/src/test/codegen/zst-offset.rs +++ b/src/test/codegen/zst-offset.rs @@ -15,7 +15,7 @@ pub fn helper(_: usize) { pub fn scalar_layout(s: &(u64, ())) { // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 8 let x = &s.1; - &x; // keep variable in an alloca + witness(&x); // keep variable in an alloca } // Check that we correctly generate a GEP for a ZST that is not included in ScalarPair layout @@ -24,7 +24,7 @@ pub fn scalar_layout(s: &(u64, ())) { pub fn scalarpair_layout(s: &(u64, u32, ())) { // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 12 let x = &s.2; - &x; // keep variable in an alloca + witness(&x); // keep variable in an alloca } #[repr(simd)] @@ -36,5 +36,8 @@ pub struct U64x4(u64, u64, u64, u64); pub fn vector_layout(s: &(U64x4, ())) { // CHECK: getelementptr i8, {{.+}}, [[USIZE]] 32 let x = &s.1; - &x; // keep variable in an alloca + witness(&x); // keep variable in an alloca } + +#[inline(never)] +fn witness(_: &impl Sized) {} From a48127f0dc019e75b2e3c96d6c37b4c022f6edc6 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 6 Dec 2022 20:05:55 +0000 Subject: [PATCH 018/223] Bless incremental test. --- src/test/incremental/hashes/closure_expressions.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index c769246b29b2..ce9f1d5a9d24 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -45,9 +45,9 @@ pub fn add_parameter() { } #[cfg(not(any(cfail1,cfail4)))] -#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail3")] -#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir, typeck")] +#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck")] #[rustc_clean(cfg="cfail6")] pub fn add_parameter() { let x = 0u32; From 0817b1d3ed26898e7d9ed71f6a2218d912ea6de5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 6 Dec 2022 23:55:26 +0000 Subject: [PATCH 019/223] Don't deduce a signature that makes a closure cyclic --- compiler/rustc_hir_typeck/src/closure.rs | 38 +++++++++-- src/test/ui/closures/supertrait-hint-cycle.rs | 65 +++++++++++++++++++ src/test/ui/issues/issue-25439.stderr | 21 +++--- .../unboxed-closure-no-cyclic-sig.stderr | 21 +++--- 4 files changed, 122 insertions(+), 23 deletions(-) create mode 100644 src/test/ui/closures/supertrait-hint-cycle.rs diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5bd02dff73bf..8167e7e070ce 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -13,7 +13,7 @@ use rustc_infer::infer::{InferOk, InferResult}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, Ty, TypeSuperVisitable, TypeVisitor}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; @@ -21,6 +21,7 @@ use rustc_trait_selection::traits::error_reporting::ArgKind; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; use std::cmp; use std::iter; +use std::ops::ControlFlow; /// What signature do we *expect* the closure to have from context? #[derive(Debug, Clone, TypeFoldable, TypeVisitable)] @@ -54,7 +55,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // closure sooner rather than later, so first examine the expected // type, and see if can glean a closure kind from there. let (expected_sig, expected_kind) = match expected.to_option(self) { - Some(ty) => self.deduce_expectations_from_expected_type(ty), + Some(ty) => self.deduce_closure_signature(ty), None => (None, None), }; let body = self.tcx.hir().body(closure.body); @@ -162,13 +163,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Given the expected type, figures out what it can about this closure we /// are about to type check: #[instrument(skip(self), level = "debug")] - fn deduce_expectations_from_expected_type( + fn deduce_closure_signature( &self, expected_ty: Ty<'tcx>, ) -> (Option>, Option) { match *expected_ty.kind() { ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => self - .deduce_signature_from_predicates( + .deduce_closure_signature_from_predicates( + expected_ty, self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs), ), ty::Dynamic(ref object_type, ..) => { @@ -181,7 +183,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .and_then(|did| self.tcx.fn_trait_kind_from_def_id(did)); (sig, kind) } - ty::Infer(ty::TyVar(vid)) => self.deduce_signature_from_predicates( + ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( + self.tcx.mk_ty_var(self.root_var(vid)), self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)), ), ty::FnPtr(sig) => { @@ -192,8 +195,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn deduce_signature_from_predicates( + fn deduce_closure_signature_from_predicates( &self, + expected_ty: Ty<'tcx>, predicates: impl DoubleEndedIterator, Span)>, ) -> (Option>, Option) { let mut expected_sig = None; @@ -214,13 +218,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if expected_sig.is_none() && let ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) = bound_predicate.skip_binder() { - expected_sig = self.normalize( + let inferred_sig = self.normalize( obligation.cause.span, self.deduce_sig_from_projection( Some(obligation.cause.span), bound_predicate.rebind(proj_predicate), ), ); + // Make sure that we didn't infer a signature that mentions itself. + // This can happen when we elaborate certain supertrait bounds that + // mention projections containing the `Self` type. See + struct MentionsTy<'tcx> { + expected_ty: Ty<'tcx>, + } + impl<'tcx> TypeVisitor<'tcx> for MentionsTy<'tcx> { + type BreakTy = (); + + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { + if t == self.expected_ty { + ControlFlow::BREAK + } else { + t.super_visit_with(self) + } + } + } + if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { + expected_sig = inferred_sig; + } } // Even if we can't infer the full signature, we may be able to diff --git a/src/test/ui/closures/supertrait-hint-cycle.rs b/src/test/ui/closures/supertrait-hint-cycle.rs new file mode 100644 index 000000000000..dbb06b2ef7a7 --- /dev/null +++ b/src/test/ui/closures/supertrait-hint-cycle.rs @@ -0,0 +1,65 @@ +// edition:2021 +// check-pass + +#![feature(type_alias_impl_trait)] +#![feature(closure_lifetime_binder)] + +use std::future::Future; + +trait AsyncFn: FnMut(I) -> Self::Fut { + type Fut: Future; +} + +impl AsyncFn for F +where + Fut: Future, + F: FnMut(I) -> Fut, +{ + type Fut = Fut; +} + +async fn call(mut ctx: C, mut f: F) -> Result +where + F: for<'a> AsyncFn<&'a mut C, Result>, +{ + loop { + match f(&mut ctx).await { + Ok(val) => return Ok(val), + Err(_) => continue, + } + } +} + +trait Cap<'a> {} +impl Cap<'_> for T {} + +fn works(ctx: &mut usize) { + let mut inner = 0; + + type Ret<'a, 'b: 'a> = impl Future> + 'a + Cap<'b>; + + let callback = for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> { + inner += 1; + async move { + let _c = c; + Ok(1usize) + } + }; + call(ctx, callback); +} + +fn doesnt_work_but_should(ctx: &mut usize) { + let mut inner = 0; + + type Ret<'a, 'b: 'a> = impl Future> + 'a + Cap<'b>; + + call(ctx, for<'a, 'b> |c: &'a mut &'b mut usize| -> Ret<'a, 'b> { + inner += 1; + async move { + let _c = c; + Ok(1usize) + } + }); +} + +fn main() {} diff --git a/src/test/ui/issues/issue-25439.stderr b/src/test/ui/issues/issue-25439.stderr index 325c28c15e27..938c9d9f18ca 100644 --- a/src/test/ui/issues/issue-25439.stderr +++ b/src/test/ui/issues/issue-25439.stderr @@ -1,14 +1,19 @@ -error[E0644]: closure/generator type that references itself - --> $DIR/issue-25439.rs:8:9 +error[E0631]: type mismatch in closure arguments + --> $DIR/issue-25439.rs:8:5 | LL | fix(|_, x| x); - | ^^^^^^^^ cyclic type of infinite size + | ^^^ ------ found signature defined here + | | + | expected due to this | - = note: closures cannot capture themselves or take themselves as argument; - this error may be the result of a recent compiler bug-fix, - see issue #46062 - for more information + = note: expected closure signature `for<'a> fn(Helper<'a, [closure@$DIR/issue-25439.rs:8:9: 8:15]>, i32) -> _` + found closure signature `fn(_, _) -> _` +note: required by a bound in `fix` + --> $DIR/issue-25439.rs:3:33 + | +LL | fn fix(f: F) -> i32 where F: Fn(Helper, i32) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `fix` error: aborting due to previous error -For more information about this error, try `rustc --explain E0644`. +For more information about this error, try `rustc --explain E0631`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr index 167479270b54..cfea13c1127c 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr @@ -1,14 +1,19 @@ -error[E0644]: closure/generator type that references itself - --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7 +error[E0631]: type mismatch in closure arguments + --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:5 | LL | g(|_| { }); - | ^^^^^^^^ cyclic type of infinite size + | ^ --- found signature defined here + | | + | expected due to this | - = note: closures cannot capture themselves or take themselves as argument; - this error may be the result of a recent compiler bug-fix, - see issue #46062 - for more information + = note: expected closure signature `fn(Option<[closure@$DIR/unboxed-closure-no-cyclic-sig.rs:8:7: 8:10]>) -> _` + found closure signature `fn(_) -> _` +note: required by a bound in `g` + --> $DIR/unboxed-closure-no-cyclic-sig.rs:5:24 + | +LL | fn g(_: F) where F: FnOnce(Option) {} + | ^^^^^^^^^^^^^^^^^ required by this bound in `g` error: aborting due to previous error -For more information about this error, try `rustc --explain E0644`. +For more information about this error, try `rustc --explain E0631`. From 9f59ab55e6e5e8825cfc36bd90ed4d5b387ecd70 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Dec 2022 03:03:35 +0000 Subject: [PATCH 020/223] Restore cyclic closure message --- compiler/rustc_hir_typeck/src/closure.rs | 2 +- .../src/traits/error_reporting/mod.rs | 21 ++++++++++++++++++- src/test/ui/issues/issue-25439.stderr | 16 +++++++------- .../unboxed-closure-no-cyclic-sig.stderr | 16 +++++++------- 4 files changed, 37 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 8167e7e070ce..3453da500b98 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); // Make sure that we didn't infer a signature that mentions itself. // This can happen when we elaborate certain supertrait bounds that - // mention projections containing the `Self` type. See + // mention projections containing the `Self` type. See #105401. struct MentionsTy<'tcx> { expected_ty: Ty<'tcx>, } 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 8f317beaa77d..fb7791879a15 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -33,7 +33,7 @@ use rustc_infer::infer::error_reporting::TypeErrCtxt; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; -use rustc_middle::ty::error::ExpectedFound; +use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{with_forced_trimmed_paths, FmtPrinter, Print}; use rustc_middle::ty::{ @@ -1215,6 +1215,25 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + OutputTypeParameterMismatch( + found_trait_ref, + expected_trait_ref, + terr @ TypeError::CyclicTy(_), + ) => { + let self_ty = found_trait_ref.self_ty().skip_binder(); + let (cause, terr) = if let ty::Closure(def_id, _) = self_ty.kind() { + ( + ObligationCause::dummy_with_span(tcx.def_span(def_id)), + TypeError::CyclicTy(self_ty), + ) + } else { + (obligation.cause.clone(), terr) + }; + self.report_and_explain_type_error( + TypeTrace::poly_trait_refs(&cause, true, expected_trait_ref, found_trait_ref), + terr, + ) + } OutputTypeParameterMismatch(found_trait_ref, expected_trait_ref, _) => { let found_trait_ref = self.resolve_vars_if_possible(found_trait_ref); let expected_trait_ref = self.resolve_vars_if_possible(expected_trait_ref); diff --git a/src/test/ui/issues/issue-25439.stderr b/src/test/ui/issues/issue-25439.stderr index 938c9d9f18ca..dadae23fdf39 100644 --- a/src/test/ui/issues/issue-25439.stderr +++ b/src/test/ui/issues/issue-25439.stderr @@ -1,13 +1,13 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-25439.rs:8:5 +error[E0644]: closure/generator type that references itself + --> $DIR/issue-25439.rs:8:9 | LL | fix(|_, x| x); - | ^^^ ------ found signature defined here - | | - | expected due to this + | ^^^^^^ cyclic type of infinite size | - = note: expected closure signature `for<'a> fn(Helper<'a, [closure@$DIR/issue-25439.rs:8:9: 8:15]>, i32) -> _` - found closure signature `fn(_, _) -> _` + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information note: required by a bound in `fix` --> $DIR/issue-25439.rs:3:33 | @@ -16,4 +16,4 @@ LL | fn fix(f: F) -> i32 where F: Fn(Helper, i32) -> i32 { error: aborting due to previous error -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0644`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr index cfea13c1127c..6d5dbca05585 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-no-cyclic-sig.stderr @@ -1,13 +1,13 @@ -error[E0631]: type mismatch in closure arguments - --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:5 +error[E0644]: closure/generator type that references itself + --> $DIR/unboxed-closure-no-cyclic-sig.rs:8:7 | LL | g(|_| { }); - | ^ --- found signature defined here - | | - | expected due to this + | ^^^ cyclic type of infinite size | - = note: expected closure signature `fn(Option<[closure@$DIR/unboxed-closure-no-cyclic-sig.rs:8:7: 8:10]>) -> _` - found closure signature `fn(_) -> _` + = note: closures cannot capture themselves or take themselves as argument; + this error may be the result of a recent compiler bug-fix, + see issue #46062 + for more information note: required by a bound in `g` --> $DIR/unboxed-closure-no-cyclic-sig.rs:5:24 | @@ -16,4 +16,4 @@ LL | fn g(_: F) where F: FnOnce(Option) {} error: aborting due to previous error -For more information about this error, try `rustc --explain E0631`. +For more information about this error, try `rustc --explain E0644`. From fa2f31b97178c3a66d6e5f91fa597711f585fd3b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Dec 2022 03:50:35 +0000 Subject: [PATCH 021/223] More tests --- .../ui/closures/supertrait-hint-cycle-2.rs | 18 ++++++++++++++++++ .../ui/closures/supertrait-hint-cycle-3.rs | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/closures/supertrait-hint-cycle-2.rs create mode 100644 src/test/ui/closures/supertrait-hint-cycle-3.rs diff --git a/src/test/ui/closures/supertrait-hint-cycle-2.rs b/src/test/ui/closures/supertrait-hint-cycle-2.rs new file mode 100644 index 000000000000..fda81b18d1e9 --- /dev/null +++ b/src/test/ui/closures/supertrait-hint-cycle-2.rs @@ -0,0 +1,18 @@ +// check-pass + +trait Foo<'a> { + type Input; +} + +impl Foo<'_> for F { + type Input = u32; +} + +trait SuperFn: for<'a> Foo<'a> + for<'a> Fn(>::Input) {} +impl SuperFn for T where T: for<'a> Fn(>::Input) + for<'a> Foo<'a> {} + +fn needs_super(_: impl SuperFn) {} + +fn main() { + needs_super(|_: u32| {}); +} diff --git a/src/test/ui/closures/supertrait-hint-cycle-3.rs b/src/test/ui/closures/supertrait-hint-cycle-3.rs new file mode 100644 index 000000000000..8149474df196 --- /dev/null +++ b/src/test/ui/closures/supertrait-hint-cycle-3.rs @@ -0,0 +1,16 @@ +// check-pass + + +trait Foo<'a> { + type Input; +} + +impl Foo<'_> for F { + type Input = u32; +} + +fn needs_super Fn(>::Input) + for<'a> Foo<'a>>(_: F) {} + +fn main() { + needs_super(|_: u32| {}); +} From 82cf6f204aeb791c38463798e2edd6b4935f1296 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Wed, 16 Nov 2022 20:08:14 -0500 Subject: [PATCH 022/223] UPDATE - migrate base.rs to new diagnostics infrastructure --- compiler/rustc_codegen_ssa/src/base.rs | 16 +++++---------- compiler/rustc_codegen_ssa/src/errors.rs | 20 +++++++++++++++++++ .../locales/en-US/codegen_ssa.ftl | 7 +++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8b34be385800..d318c15d3422 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -5,6 +5,7 @@ use crate::back::write::{ submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, }; use crate::common::{IntPredicate, RealPredicate, TypeKind}; +use crate::errors; use crate::meth; use crate::mir; use crate::mir::operand::OperandValue; @@ -451,10 +452,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. let span = cx.tcx().def_span(rust_main_def_id); - cx.sess() - .struct_span_err(span, "entry symbol `main` declared multiple times") - .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") - .emit(); + cx.sess().emit_err(errors::MultipleMainFunctions { span }); cx.sess().abort_if_errors(); bug!(); }; @@ -595,8 +593,8 @@ pub fn codegen_crate( &metadata, &exported_symbols::metadata_symbol_name(tcx), ); - if let Err(err) = std::fs::write(&file_name, data) { - tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); + if let Err(error) = std::fs::write(&file_name, data) { + tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error }); } Some(CompiledModule { name: metadata_cgu_name, @@ -815,11 +813,7 @@ impl CrateInfo { let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != sym::windows && subsystem != sym::console { - tcx.sess.fatal(&format!( - "invalid windows subsystem `{}`, only \ - `windows` and `console` are allowed", - subsystem - )); + tcx.sess.emit_fatal(errors::InvalidWindowsSubsystem { subsystem }); } subsystem.to_string() }); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 0620000201f0..9179fe03d3f6 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -555,3 +555,23 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_multiple_main_functions)] +#[help] +pub struct MultipleMainFunctions { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_metadata_object_file_write)] +pub struct MetadataObjectFileWrite { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_windows_subsystem)] +pub struct InvalidWindowsSubsystem { + pub subsystem: Symbol, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index db4c82b35c77..1863dae258ff 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -194,3 +194,10 @@ codegen_ssa_unknown_archive_kind = Don't know how to build archive of type: {$kind} codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` + +codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times + .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + +codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} + +codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed From 78796ba637d9c8b575e977ddfc9351e4f1626319 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 5 Nov 2022 23:54:42 -0400 Subject: [PATCH 023/223] ADD - fixme in type_names.rs until we are able to translate InterpError --- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 3ae6c531b445..1599ccbb2594 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -93,6 +93,7 @@ fn push_debuginfo_type_name<'tcx>( Err(e) => { // Computing the layout can still fail here, e.g. if the target architecture // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961. + // FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable. tcx.sess.fatal(&format!("{}", e)); } } From d41112a8c5f0b85649b4f0e1663edf15f7f2601e Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 6 Nov 2022 10:09:24 -0500 Subject: [PATCH 024/223] UPDATE - migrate constant.rs to new diagnostics infrastructure --- compiler/rustc_codegen_ssa/src/errors.rs | 14 ++++++++++++++ compiler/rustc_codegen_ssa/src/mir/constant.rs | 5 +++-- .../locales/en-US/codegen_ssa.ftl | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 9179fe03d3f6..de0a80280be9 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -575,3 +575,17 @@ pub struct MetadataObjectFileWrite { pub struct InvalidWindowsSubsystem { pub subsystem: Symbol, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_erroneous_constant)] +pub struct ErroneousConstant { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_shuffle_indices_evaluation)] +pub struct ShuffleIndicesEvaluation { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 53ff3c240962..3cae19b241d6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,3 +1,4 @@ +use crate::errors; use crate::mir::operand::OperandRef; use crate::traits::*; use rustc_middle::mir; @@ -44,7 +45,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| { match err { ErrorHandled::Reported(_) => { - self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); + self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span }); } ErrorHandled::TooGeneric => { span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err); @@ -87,7 +88,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (llval, c.ty()) }) .unwrap_or_else(|_| { - bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time"); + bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span }); // We've errored, so we don't have to produce working code. let ty = self.monomorphize(ty); let llty = bx.backend_type(bx.layout_of(ty)); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 1863dae258ff..88fb7ce8d9f7 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -201,3 +201,7 @@ codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple time codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed + +codegen_ssa_erroneous_constant = erroneous constant encountered + +codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time From e26366ad99a6da4df5c9b476eff00c48e50d1774 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 13 Nov 2022 14:03:22 -0500 Subject: [PATCH 025/223] [WIP] UPDATE - migrate intrinsic.rs to new diagnostic infrastructure WIP - replacing span_invalid_monomorphization_error function. Still in progress due to its use in codegen_llvm inside macros --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 13 ++-- compiler/rustc_codegen_ssa/src/errors.rs | 43 +++++++++++++ .../rustc_codegen_ssa/src/mir/intrinsic.rs | 64 ++++--------------- .../locales/en-US/codegen_ssa.ftl | 14 ++++ 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1ce48f82e1c9..82c6c3894947 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -10,6 +10,7 @@ use crate::value::Value; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; +use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; @@ -284,15 +285,11 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - tcx.sess, + tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + name, + ty, + }); return; } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index de0a80280be9..7303ab967975 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -6,6 +6,7 @@ use rustc_errors::{ IntoDiagnosticArg, }; use rustc_macros::Diagnostic; +use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; use std::borrow::Cow; use std::io::Error; @@ -589,3 +590,45 @@ pub struct ShuffleIndicesEvaluation { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_missing_memory_ordering)] +pub struct MissingMemoryOrdering; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_atomic_ordering)] +pub struct UnknownAtomicOrdering; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_atomic_compare_exchange)] +pub struct AtomicCompareExchange; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_atomic_operation)] +pub struct UnknownAtomicOperation; + +#[derive(Diagnostic)] +pub enum InvalidMonomorphization<'tcx> { + #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")] + BasicIntegerType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")] + BasicFloatType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")] + FloatToIntUnchecked { + #[primary_span] + span: Span, + ty: Ty<'tcx>, + }, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index a75609260eda..766dc74cbbb6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,7 +1,9 @@ use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; use super::FunctionCx; -use crate::common::{span_invalid_monomorphization_error, IntPredicate}; +use crate::common::IntPredicate; +use crate::errors; +use crate::errors::InvalidMonomorphization; use crate::glue; use crate::meth; use crate::traits::*; @@ -305,15 +307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); return; } } @@ -329,15 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic float type, found `{}`", - name, arg_tys[0] - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicFloatType { span, name, ty: arg_tys[0] }); return; } } @@ -345,29 +331,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::float_to_int_unchecked => { if float_type_width(arg_tys[0]).is_none() { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ - intrinsic: expected basic float type, \ - found `{}`", - arg_tys[0] - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: arg_tys[0] }); return; } let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ - intrinsic: expected basic integer type, \ - found `{}`", - ret_ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: ret_ty }); return; }; if signed { @@ -402,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use crate::common::{AtomicRmwBinOp, SynchronizationScope}; let Some((instruction, ordering)) = atomic.split_once('_') else { - bx.sess().fatal("Atomic intrinsic missing memory ordering"); + bx.sess().emit_fatal(errors::MissingMemoryOrdering); }; let parse_ordering = |bx: &Bx, s| match s { @@ -412,25 +380,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "release" => Release, "acqrel" => AcquireRelease, "seqcst" => SequentiallyConsistent, - _ => bx.sess().fatal("unknown ordering in atomic intrinsic"), + _ => bx.sess().emit_fatal(errors::UnknownAtomicOrdering), }; let invalid_monomorphization = |ty| { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); }; match instruction { "cxchg" | "cxchgweak" => { let Some((success, failure)) = ordering.split_once('_') else { - bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering"); + bx.sess().emit_fatal(errors::AtomicCompareExchange); }; let ty = substs.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { @@ -529,7 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "min" => AtomicRmwBinOp::AtomicMin, "umax" => AtomicRmwBinOp::AtomicUMax, "umin" => AtomicRmwBinOp::AtomicUMin, - _ => bx.sess().fatal("unknown atomic operation"), + _ => bx.sess().emit_fatal(errors::UnknownAtomicOperation), }; let ty = substs.type_at(0); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 88fb7ce8d9f7..889d29003719 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -205,3 +205,17 @@ codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}` codegen_ssa_erroneous_constant = erroneous constant encountered codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time + +codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering + +codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic + +codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering + +codegen_ssa_unknown_atomic_operation = unknown atomic operation + +codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` From d1030fab229d25d3ca14b1aaa2fc8e5a6ec932a8 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Thu, 17 Nov 2022 08:53:14 -0500 Subject: [PATCH 026/223] UPDATE - migrate fn simd_simple_float_intrinsic error messages --- Cargo.lock | 2 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 41 ++++++------------- compiler/rustc_codegen_ssa/Cargo.toml | 1 + compiler/rustc_codegen_ssa/src/errors.rs | 25 +++++++++++ .../locales/en-US/codegen_ssa.ftl | 6 +++ compiler/rustc_errors/Cargo.toml | 1 + compiler/rustc_errors/src/diagnostic_impls.rs | 7 ++++ 7 files changed, 55 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97148641670f..6f630b479ed2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3636,6 +3636,7 @@ dependencies = [ "rustc_span", "rustc_symbol_mangling", "rustc_target", + "rustc_type_ir", "serde_json", "smallvec", "snap", @@ -3770,6 +3771,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "serde", "serde_json", "termcolor", diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 82c6c3894947..032063d23b6d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1165,42 +1165,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { - #[allow(unused_macro_rules)] - macro_rules! emit_error { - ($msg: tt) => { - emit_error!($msg, ) - }; - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } - macro_rules! return_error { - ($($fmt: tt)*) => { - { - emit_error!($($fmt)*); - return Err(()); - } - } - } - let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), _ => { - return_error!( - "unsupported element type `{}` of floating-point vector `{}`", - f.name_str(), - in_ty - ); + bx.sess().emit_err(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty, + }); + return Err(()); } } } else { - return_error!("`{}` is not a floating-point type", in_ty); + bx.sess().emit_err(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + return Err(()); }; let vec_ty = bx.type_vector(elem_ty, in_len); @@ -1222,7 +1204,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), - _ => return_error!("unrecognized intrinsic `{}`", name), + _ => { + bx.sess().emit_err(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }); + return Err(()); + } }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 345174fb595a..d1ad687e6aee 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -27,6 +27,7 @@ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } +rustc_type_ir = { path = "../rustc_type_ir" } rustc_attr = { path = "../rustc_attr" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 7303ab967975..5ecba6925fab 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -8,6 +8,7 @@ use rustc_errors::{ use rustc_macros::Diagnostic; use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; +use rustc_type_ir::FloatTy; use std::borrow::Cow; use std::io::Error; use std::path::{Path, PathBuf}; @@ -631,4 +632,28 @@ pub enum InvalidMonomorphization<'tcx> { span: Span, ty: Ty<'tcx>, }, + + #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")] + FloatingPointVector { + #[primary_span] + span: Span, + name: Symbol, + f_ty: FloatTy, + in_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")] + FloatingPointType { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")] + UnrecognizedIntrinsic { + #[primary_span] + span: Span, + name: Symbol, + }, } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 889d29003719..0d9a9d851fc6 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -219,3 +219,9 @@ codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphizati codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` + +codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type + +codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index dee7a31ec202..cadd53fbd835 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -17,6 +17,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_target = { path = "../rustc_target" } rustc_hir = { path = "../rustc_hir" } rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_type_ir = { path = "../rustc_type_ir" } unicode-width = "0.1.4" termcolor = "1.0" annotate-snippets = "0.9" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 628cb90903fe..794b6efcc2b2 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -9,6 +9,7 @@ use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_target::abi::TargetDataLayoutErrors; use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; +use rustc_type_ir as type_ir; use std::borrow::Cow; use std::fmt; use std::num::ParseIntError; @@ -170,6 +171,12 @@ impl IntoDiagnosticArg for ast::token::TokenKind { } } +impl IntoDiagnosticArg for type_ir::FloatTy { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Borrowed(self.name_str())) + } +} + impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(match self { From 27744460e2d0b960a55a28637ba46835484e4335 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Wed, 23 Nov 2022 01:07:36 -0500 Subject: [PATCH 027/223] ADD - create and emit Bug support for Diagnostics UPDATE - migrate constant span_bug to translatable diagnostic. --- compiler/rustc_codegen_ssa/src/errors.rs | 7 +++ .../rustc_codegen_ssa/src/mir/constant.rs | 6 +- .../locales/en-US/codegen_ssa.ftl | 2 + .../rustc_errors/src/diagnostic_builder.rs | 55 ++++++++++++++++++- compiler/rustc_errors/src/lib.rs | 14 +++++ 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 5ecba6925fab..852925a1787c 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -585,6 +585,13 @@ pub struct ErroneousConstant { pub span: Span, } +#[derive(Diagnostic)] +#[diag(codegen_ssa_polymorphic_constant_too_generic)] +pub struct PolymorphicConstantTooGeneric { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(codegen_ssa_shuffle_indices_evaluation)] pub struct ShuffleIndicesEvaluation { diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 3cae19b241d6..14fe84a146da 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -48,7 +48,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span }); } ErrorHandled::TooGeneric => { - span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err); + self.cx + .tcx() + .sess + .diagnostic() + .emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span }); } } err diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 0d9a9d851fc6..d10c399bb6af 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -225,3 +225,5 @@ codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphiz codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` + +codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index a2ed988643ff..cbfee582d871 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,7 +1,7 @@ use crate::diagnostic::IntoDiagnosticArg; use crate::{ Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, - SubdiagnosticMessage, + ExplicitBug, SubdiagnosticMessage, }; use crate::{Handler, Level, MultiSpan, StashKey}; use rustc_lint_defs::Applicability; @@ -12,6 +12,7 @@ use std::borrow::Cow; use std::fmt::{self, Debug}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; +use std::panic; use std::thread::panicking; /// Trait implemented by error types. This should not be implemented manually. Instead, use @@ -308,6 +309,58 @@ impl EmissionGuarantee for Noted { } } +/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for +/// bug struct diagnostics. +#[derive(Copy, Clone)] +pub struct Bug; + +impl<'a> DiagnosticBuilder<'a, Bug> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + #[track_caller] + pub(crate) fn new_bug(handler: &'a Handler, message: impl Into) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message); + Self::new_diagnostic_bug(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic bug"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for Bug { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + // Then panic. No need to return the marker type. + panic::panic_any(ExplicitBug); + } + + fn make_diagnostic_builder( + handler: &Handler, + msg: impl Into, + ) -> DiagnosticBuilder<'_, Self> { + DiagnosticBuilder::new_bug(handler, msg) + } +} + impl<'a> DiagnosticBuilder<'a, !> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b03352d5fec6..cf9741366a18 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1127,6 +1127,20 @@ impl Handler { self.create_fatal(fatal).emit() } + pub fn create_bug<'a>( + &'a self, + bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, + ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { + bug.into_diagnostic(self) + } + + pub fn emit_bug<'a>( + &'a self, + bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, + ) -> diagnostic_builder::Bug { + self.create_bug(bug).emit() + } + fn emit_diag_at_span( &self, mut diag: Diagnostic, From 29d8c87fe88f51bdc7e6197e2e8eed7adc898f49 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 26 Nov 2022 20:28:01 -0500 Subject: [PATCH 028/223] DELETE - fn span_invalid_monomorphization_error and localize intrinsics macros --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 529 ++++++++++-------- compiler/rustc_codegen_ssa/src/common.rs | 6 - compiler/rustc_codegen_ssa/src/errors.rs | 322 +++++++++++ .../locales/en-US/codegen_ssa.ftl | 66 +++ 4 files changed, 670 insertions(+), 253 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 032063d23b6d..680d810f78eb 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -8,9 +8,8 @@ use crate::va_arg::emit_va_arg; use crate::value::Value; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; -use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; @@ -835,40 +834,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( llret_ty: &'ll Type, span: Span, ) -> Result<&'ll Value, ()> { - // macros for error handling: - #[allow(unused_macro_rules)] - macro_rules! emit_error { - ($msg: tt) => { - emit_error!($msg, ) - }; - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } - macro_rules! return_error { - ($($fmt: tt)*) => { - { - emit_error!($($fmt)*); - return Err(()); - } - } + ($diag: expr) => {{ + bx.sess().emit_err($diag); + return Err(()); + }}; } macro_rules! require { - ($cond: expr, $($fmt: tt)*) => { + ($cond: expr, $diag: expr) => { if !$cond { - return_error!($($fmt)*); + return_error!($diag); } }; } macro_rules! require_simd { - ($ty: expr, $position: expr) => { - require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) + ($ty: expr, $diag: expr) => { + require!($ty.is_simd(), $diag) }; } @@ -878,7 +861,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], "argument"); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); + let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -899,12 +886,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); bx.load(int_ty, ptr, Align::ONE) } - _ => return_error!( - "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`", + _ => return_error!(InvalidMonomorphization::InvalidBitmask { + span, + name, mask_ty, expected_int_bits, expected_bytes - ), + }), }; let i1 = bx.type_i1(); @@ -916,7 +904,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } // every intrinsic below takes a SIMD vector as its first argument - require_simd!(arg_tys[0], "input"); + require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] }); let in_ty = arg_tys[0]; let comparison = match name { @@ -931,23 +919,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); if let Some(cmp_op) = comparison { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, - "expected return type with integer elements, found `{}` with non-integer `{}`", - ret_ty, - out_ty + InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } ); return Ok(compare_simd_types( @@ -972,10 +961,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span_bug!(span, "could not evaluate shuffle index array length") }) } - _ => return_error!( - "simd_shuffle index must be an array of `u32`, got `{}`", - args[2].layout.ty - ), + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), } } else { stripped.parse().unwrap_or_else(|_| { @@ -983,23 +973,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( }) }; - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, - "expected return type of length {}, found `{}` with length {}", - n, - ret_ty, - out_len + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } ); require!( in_elem == out_ty, - "expected return element type `{}` (element of input `{}`), \ - found `{}` with element type `{}`", - in_elem, - in_ty, - ret_ty, - out_ty + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } ); let total_len = u128::from(in_len) * 2; @@ -1012,15 +994,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let val = bx.const_get_elt(vector, i as u64); match bx.const_to_opt_u128(val, true) { None => { - emit_error!("shuffle index #{} is not a constant", arg_idx); + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexNotConstant { + span, + name, + arg_idx, + }); None } Some(idx) if idx >= total_len => { - emit_error!( - "shuffle index #{} is out of bounds (limit {})", + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds { + span, + name, arg_idx, - total_len - ); + total_len, + }); None } Some(idx) => Some(bx.const_i32(idx as i32)), @@ -1041,10 +1028,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - "expected inserted type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - arg_tys[2] + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } ); return Ok(bx.insert_element( args[0].immediate(), @@ -1055,10 +1045,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_extract { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())); } @@ -1066,17 +1053,18 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], "argument"); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, - "mismatched lengths: mask length `{}` != other vector length `{}`", - m_len, - v_len + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } ); match m_elem_ty.kind() { ty::Int(_) => {} - _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty), + _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), } // truncate the mask to a vector of i1s let i1 = bx.type_i1(); @@ -1108,11 +1096,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( args[0].immediate(), i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), ), - _ => return_error!( - "vector argument `{}`'s element type `{}`, expected integer element type", + _ => return_error!(InvalidMonomorphization::VectorArgument { + span, + name, in_ty, in_elem - ), + }), }; // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position. @@ -1147,12 +1136,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty)); return Ok(bx.load(array_ty, ptr, Align::ONE)); } - _ => return_error!( - "cannot return `{}`, expected `u{}` or `[u8; {}]`", + _ => return_error!(InvalidMonomorphization::CannotReturn { + span, + name, ret_ty, expected_int_bits, expected_bytes - ), + }), } } @@ -1165,24 +1155,27 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { + macro_rules! return_error { + ($diag: expr) => {{ + bx.sess().emit_err($diag); + return Err(()); + }}; + } + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), - _ => { - bx.sess().emit_err(InvalidMonomorphization::FloatingPointVector { - span, - name, - f_ty: *f, - in_ty, - }); - return Err(()); - } + _ => return_error!(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty, + }), } } else { - bx.sess().emit_err(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); - return Err(()); + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); }; let vec_ty = bx.type_vector(elem_ty, in_len); @@ -1204,10 +1197,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), - _ => { - bx.sess().emit_err(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }); - return Err(()); - } + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); @@ -1301,37 +1291,48 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); - require_simd!(ret_ty, "return"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "second", - in_len, - in_ty, - arg_tys[1], - out_len + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len + } ); require!( in_len == out_len2, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "third", - in_len, - in_ty, - arg_tys[2], - out_len2 + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: out_len2 + } ); // The return type must match the first argument type - require!(ret_ty == in_ty, "expected return type `{}`, found `{}`", in_ty, ret_ty); + require!( + ret_ty == in_ty, + InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -1358,15 +1359,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*_ {}`", - element_ty1, - arg_tys[1], - in_elem, - in_ty, - element_ty1, - in_elem + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Not, + } ); unreachable!(); } @@ -1382,10 +1383,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of third argument `{}` \ - to be a signed integer type", - element_ty2, - arg_tys[2] + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } ); } } @@ -1434,32 +1437,40 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == element_len1, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "second", - in_len, - in_ty, - arg_tys[1], - element_len1 + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len: element_len1 + } ); require!( in_len == element_len2, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "third", - in_len, - in_ty, - arg_tys[2], - element_len2 + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: element_len2 + } ); // This counts how many pointers @@ -1490,15 +1501,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*mut {}`", - element_ty1, - arg_tys[1], - in_elem, - in_ty, - element_ty1, - in_elem + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Mut, + } ); unreachable!(); } @@ -1513,10 +1524,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of third argument `{}` \ - be a signed integer type", - element_ty2, - arg_tys[2] + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } ); } } @@ -1563,10 +1576,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { @@ -1589,25 +1599,28 @@ fn generic_simd_intrinsic<'ll, 'tcx>( 32 => bx.const_real(bx.type_f32(), $identity), 64 => bx.const_real(bx.type_f64(), $identity), v => return_error!( - r#" -unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, - sym::$name, - in_ty, - in_elem, - v, - ret_ty + InvalidMonomorphization::UnsupportedSymbolOfSize { + span, + name, + symbol: sym::$name, + in_ty, + in_elem, + size: v, + ret_ty + } ), } }; Ok(bx.$float_reduce(acc, args[0].immediate())) } - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1635,22 +1648,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_i) => Ok(bx.$int_red(args[0].immediate(), true)), ty::Uint(_u) => Ok(bx.$int_red(args[0].immediate(), false)), ty::Float(_f) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1668,22 +1679,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let input = if !$boolean { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); args[0].immediate() } else { match in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), } // boolean reductions operate on vectors of i1s: @@ -1696,13 +1705,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let r = bx.$red(input); Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) }) } - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1715,16 +1725,18 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bitwise_red!(simd_reduce_any: vector_reduce_or, true); if name == sym::simd_cast_ptr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { @@ -1733,9 +1745,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); assert!(!check_sized); // we are in codegen, so we shouldn't see these types - require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem) + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) } - _ => return_error!("expected pointer, got `{}`", in_elem), } match out_elem.kind() { ty::RawPtr(p) => { @@ -1743,9 +1760,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); assert!(!check_sized); // we are in codegen, so we shouldn't see these types - require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem) + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) } - _ => return_error!("expected pointer, got `{}`", out_elem), } if in_elem == out_elem { @@ -1756,66 +1778,76 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } if name == sym::simd_expose_addr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { ty::RawPtr(_) => {} - _ => return_error!("expected pointer, got `{}`", in_elem), + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) + } } match out_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} - _ => return_error!("expected `usize`, got `{}`", out_elem), + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: out_elem }), } return Ok(bx.ptrtoint(args[0].immediate(), llret_ty)); } if name == sym::simd_from_exposed_addr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} - _ => return_error!("expected `usize`, got `{}`", in_elem), + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }), } match out_elem.kind() { ty::RawPtr(_) => {} - _ => return_error!("expected pointer, got `{}`", out_elem), + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) + } } return Ok(bx.inttoptr(args[0].immediate(), llret_ty)); } if name == sym::simd_cast || name == sym::simd_as { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); // casting cares about nominal type, not just structural type if in_elem == out_elem { @@ -1894,11 +1926,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } require!( false, - "unsupported cast from `{}` with element `{}` to `{}` with element `{}`", - in_ty, - in_elem, - ret_ty, - out_elem + InvalidMonomorphization::UnsupportedCast { + span, + name, + in_ty, + in_elem, + ret_ty, + out_elem + } ); } macro_rules! arith_binary { @@ -1910,10 +1945,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + require!( + false, + InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem } + ); })* } } @@ -1941,10 +1976,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + require!( + false, + InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem } + ); })* } } @@ -1982,12 +2017,12 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)), _ => { - return_error!( - "expected element type `{}` of vector type `{}` \ - to be a signed or unsigned integer type", - arg_tys[0].simd_size_and_type(bx.tcx()).1, - arg_tys[0] - ); + return_error!(InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1, + vector_type: arg_tys[0] + }); } }; let llvm_intrinsic = &format!( diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 71f9179d02cc..e1abb73a504a 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,10 +1,8 @@ #![allow(non_camel_case_types)] -use rustc_errors::struct_span_err; use rustc_hir::LangItem; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; -use rustc_session::Session; use rustc_span::Span; use crate::base; @@ -193,10 +191,6 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { - struct_span_err!(a, b, E0511, "{}", c).emit(); -} - pub fn asm_const_to_str<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 852925a1787c..29876b954224 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -663,4 +663,326 @@ pub enum InvalidMonomorphization<'tcx> { span: Span, name: Symbol, }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")] + SimdArgument { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")] + SimdInput { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")] + SimdFirst { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")] + SimdSecond { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")] + SimdThird { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")] + SimdReturn { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")] + InvalidBitmask { + #[primary_span] + span: Span, + name: Symbol, + mask_ty: Ty<'tcx>, + expected_int_bits: u64, + expected_bytes: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")] + ReturnLengthInputType { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")] + SecondArgumentLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + arg_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")] + ThirdArgumentLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + arg_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")] + ReturnIntegerType { + #[primary_span] + span: Span, + name: Symbol, + ret_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")] + SimdShuffle { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")] + ReturnLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + ret_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")] + ReturnElement { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")] + ShuffleIndexNotConstant { + #[primary_span] + span: Span, + name: Symbol, + arg_idx: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")] + ShuffleIndexOutOfBounds { + #[primary_span] + span: Span, + name: Symbol, + arg_idx: u64, + total_len: u128, + }, + + #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")] + InsertedType { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")] + ReturnType { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")] + ExpectedReturnType { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")] + MismatchedLengths { + #[primary_span] + span: Span, + name: Symbol, + m_len: u64, + v_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")] + MaskType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")] + VectorArgument { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")] + CannotReturn { + #[primary_span] + span: Span, + name: Symbol, + ret_ty: Ty<'tcx>, + expected_int_bits: u64, + expected_bytes: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")] + ExpectedElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + second_arg: Ty<'tcx>, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + mutability: ExpectedPointerMutability, + }, + + #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")] + ThirdArgElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + third_arg: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")] + UnsupportedSymbolOfSize { + #[primary_span] + span: Span, + name: Symbol, + symbol: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + size: u64, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")] + UnsupportedSymbol { + #[primary_span] + span: Span, + name: Symbol, + symbol: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")] + CastFatPointer { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")] + ExpectedPointer { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")] + ExpectedUsize { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")] + UnsupportedCast { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")] + UnsupportedOperation { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")] + ExpectedVectorElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + vector_type: Ty<'tcx>, + }, +} + +pub enum ExpectedPointerMutability { + Mut, + Not, +} + +impl IntoDiagnosticArg for ExpectedPointerMutability { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self { + ExpectedPointerMutability::Mut => DiagnosticArgValue::Str(Cow::Borrowed("*mut")), + ExpectedPointerMutability::Not => DiagnosticArgValue::Str(Cow::Borrowed("*_")), + } + } } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index d10c399bb6af..c59c992afb23 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -226,4 +226,70 @@ codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphizat codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` +codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric + +codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` + +codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` + +codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` + +codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant + +codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len}) + +codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` + +codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` + +codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` + +codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type + +codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + +codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` + +codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type + +codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}` + +codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` + +codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` + +codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` + +codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` + +codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type From 4d63d7d91c984342afd5bca0c5cf4cb1761973bf Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 26 Nov 2022 21:12:44 -0500 Subject: [PATCH 029/223] UPDATE - migrate outstanding diagnostic in link.rs --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index edde1537b81e..5324214ac78c 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2612,7 +2612,7 @@ fn add_static_crate<'a>( sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); let mut archive = archive_builder_builder.new_archive_builder(sess); - if let Err(e) = archive.add_archive( + if let Err(error) = archive.add_archive( cratepath, Box::new(move |f| { if f == METADATA_FILENAME { @@ -2652,7 +2652,7 @@ fn add_static_crate<'a>( false }), ) { - sess.fatal(&format!("failed to build archive from rlib: {}", e)); + sess.emit_fatal(errors::RlibArchiveBuildFailure { error }); } if archive.build(&dst) { link_upstream(&dst); From 8360a40a8a2ff2098eed561dd89c577349dbbb76 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 8 Sep 2022 22:28:00 +0300 Subject: [PATCH 030/223] Migrate named_anon_conflict.rs --- .../locales/en-US/infer.ftl | 11 ++++++ compiler/rustc_infer/src/errors/mod.rs | 24 +++++++++++- .../nice_region_error/named_anon_conflict.rs | 38 +++++++------------ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index c9d83746d545..40ca2c1cd162 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -172,3 +172,14 @@ infer_msl_unmet_req = because this has an unmet lifetime requirement infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement infer_suggest_add_let_for_letchains = consider adding `let` + +infer_explicit_lifetime_required = explicit lifetime required in {$ident_kind -> + [ident] the type of `{$simple_ident}` + *[param_type] parameter type +} + .label = lifetime `{$named}` required + +infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$ident_kind -> + [ident] the type of `{$simple_ident}` + *[param_type] type +} diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index c4f11472d554..99112397c7f6 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -357,8 +357,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels { pub struct AddLifetimeParamsSuggestion<'a> { pub tcx: TyCtxt<'a>, pub sub: Region<'a>, - pub ty_sup: &'a Ty<'a>, - pub ty_sub: &'a Ty<'a>, + pub ty_sup: &'a hir::Ty<'a>, + pub ty_sub: &'a hir::Ty<'a>, pub add_note: bool, } @@ -520,3 +520,23 @@ pub struct MismatchedStaticLifetime<'a> { #[subdiagnostic] pub implicit_static_lifetimes: Vec, } + +#[derive(SessionDiagnostic)] +#[diag(infer::explicit_lifetime_required, code = "E0621")] +pub struct ExplicitLifetimeRequired<'a> { + #[primary_span] + #[label] + pub span: Span, + pub ident_kind: &'static str, + pub simple_ident: String, + pub named: String, + + #[suggestion( + infer::explicit_lifetime_required_sugg, + code = "{new_ty}", + applicability = "unspecified" + )] + pub new_ty_span: Span, + #[skip_arg] + pub new_ty: Ty<'a>, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 3fe7c1598fc3..d7751158902b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -1,8 +1,11 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where one region is named and the other is anonymous. -use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use crate::{ + errors::ExplicitLifetimeRequired, + infer::error_reporting::nice_region_error::find_anon_type::find_anon_type, +}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_middle::ty; use rustc_span::symbol::kw; @@ -87,30 +90,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return None; } - let (error_var, span_label_var) = match param.pat.simple_ident() { - Some(simple_ident) => ( - format!("the type of `{}`", simple_ident), - format!("the type of `{}`", simple_ident), - ), - None => ("parameter type".to_owned(), "type".to_owned()), + let simple_ident = param.pat.simple_ident(); + let (ident_kind, simple_ident) = match simple_ident { + Some(ident) => ("ident", ident.to_string()), + None => ("param_type", String::new()), }; - let mut diag = struct_span_err!( - self.tcx().sess, - span, - E0621, - "explicit lifetime required in {}", - error_var - ); + let named = named.to_string(); - diag.span_label(span, format!("lifetime `{}` required", named)); - diag.span_suggestion( - new_ty_span, - &format!("add explicit lifetime `{}` to {}", named, span_label_var), - new_ty, - Applicability::Unspecified, - ); - - Some(diag) + let err = + ExplicitLifetimeRequired { span, ident_kind, simple_ident, named, new_ty_span, new_ty }; + let err = self.tcx().sess.parse_sess.create_err(err); + Some(err) } } From 2118ff401f64789b6a9e64134d6d2797efee4be9 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 11 Sep 2022 00:45:38 +0300 Subject: [PATCH 031/223] Migrate placeholder_error.rs --- .../locales/en-US/infer.ftl | 28 ++ compiler/rustc_infer/src/errors/mod.rs | 41 +++ .../nice_region_error/placeholder_error.rs | 253 +++++++++--------- 3 files changed, 191 insertions(+), 131 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 40ca2c1cd162..a52ac1339468 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -183,3 +183,31 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id [ident] the type of `{$simple_ident}` *[param_type] type } + +infer_actual_impl_expl_1 = {$leading_ellipsis -> + [true] ... + *[false] {""} +}{$kind -> + [signature] closure with signature `{$ty_or_sig}` must implement `{$trait_path}` + [passive] `{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` + *[other] `{$ty_or_sig}` must implement `{$trait_path}` +}{$lt_kind -> + [two] , for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... + [any] , for any lifetime `'{$lifetime_1}`... + [some] , for some specific lifetime `'{lifetime_1}`... + *[nothing] {""} +} + +infer_actual_impl_expl_2 = {$kind_2 -> + [implements_trait] ...but it actually implements `{$trait_path_2}` + [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` + *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` +}{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} + +infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough + .label_satisfy = doesn't satisfy where-clause + .label_where = due to a where-clause on `{$def_id}`... + .label_dup = implementation of `{$trait_def_id}` is not general enough diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 99112397c7f6..f694c5ca4097 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -540,3 +540,44 @@ pub struct ExplicitLifetimeRequired<'a> { #[skip_arg] pub new_ty: Ty<'a>, } + +#[derive(SessionSubdiagnostic)] +pub enum ActualImplExplNotes { + // Field names have to be different across all variants + #[note(infer::actual_impl_expl_1)] + NoteOne { + leading_ellipsis: bool, + kind: &'static str, + ty_or_sig: String, + trait_path: String, + lt_kind: &'static str, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_2)] + NoteTwo { + kind_2: &'static str, + trait_path_2: String, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::trait_placeholder_mismatch)] +pub struct TraitPlaceholderMismatch { + #[primary_span] + pub span: Span, + #[label(infer::label_satisfy)] + pub satisfy_span: Option, + #[label(infer::label_where)] + pub where_span: Option, + #[label(infer::label_dup)] + pub dup_span: Option, + pub def_id: String, + pub trait_def_id: String, + + #[subdiagnostic] + pub actual_impl_expl_notes: Vec, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index fed9fda74bfb..d9fc2ec243f1 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,10 +1,11 @@ +use crate::errors::{ActualImplExplNotes, TraitPlaceholderMismatch}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::intern::Interned; -use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::ExpectedFound; @@ -12,7 +13,7 @@ use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt}; -use std::fmt::{self, Write}; +use std::fmt; impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and @@ -205,26 +206,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_substs: SubstsRef<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let span = cause.span(); - let msg = format!( - "implementation of `{}` is not general enough", - self.tcx().def_path_str(trait_def_id), - ); - let mut err = self.tcx().sess.struct_span_err(span, &msg); - let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) - | ObligationCauseCode::ExprItemObligation(def_id, ..) = - *cause.code() - { - err.span_label(span, "doesn't satisfy where-clause"); - err.span_label( - self.tcx().def_span(def_id), - &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)), - ); - true - } else { - err.span_label(span, &msg); - false - }; + let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = + if let ObligationCauseCode::ItemObligation(def_id) + | ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code() + { + ( + true, + Some(span), + Some(self.tcx().def_span(def_id)), + None, + self.tcx().def_path_str(def_id), + ) + } else { + (false, None, None, Some(span), String::new()) + }; let expected_trait_ref = self .cx @@ -284,8 +280,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ?expected_self_ty_has_vid, ); - self.explain_actual_impl_that_was_found( - &mut err, + let actual_impl_expl_notes = self.explain_actual_impl_that_was_found( sub_placeholder, sup_placeholder, has_sub, @@ -299,7 +294,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { leading_ellipsis, ); - err + let diag = TraitPlaceholderMismatch { + span, + satisfy_span, + where_span, + dup_span, + def_id, + trait_def_id: self.tcx().def_path_str(trait_def_id), + actual_impl_expl_notes, + }; + + self.tcx().sess.create_err(diag) } /// Add notes with details about the expected and actual trait refs, with attention to cases @@ -309,7 +314,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { /// due to the number of combinations we have to deal with. fn explain_actual_impl_that_was_found( &self, - err: &mut Diagnostic, sub_placeholder: Option>, sup_placeholder: Option>, has_sub: Option, @@ -321,7 +325,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_has_vid: Option, any_self_ty_has_vid: bool, leading_ellipsis: bool, - ) { + ) -> Vec { // HACK(eddyb) maybe move this in a more central location. #[derive(Copy, Clone)] struct Highlighted<'tcx, T> { @@ -380,120 +384,107 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref); expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub); expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup); - err.note(&{ - let passive_voice = match (has_sub, has_sup) { - (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, - (None, None) => { - expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); - match expected_has_vid { - Some(_) => true, - None => any_self_ty_has_vid, - } - } - }; - let mut note = if same_self_type { - let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); - self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); - - if self_ty.value.is_closure() - && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) - { - let closure_sig = self_ty.map(|closure| { - if let ty::Closure(_, substs) = closure.kind() { - self.tcx().signature_unclosure( - substs.as_closure().sig(), - rustc_hir::Unsafety::Normal, - ) - } else { - bug!("type is not longer closure"); - } - }); - - format!( - "{}closure with signature `{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - closure_sig, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - } else { - format!( - "{}`{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - self_ty, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - } - } else if passive_voice { - format!( - "{}`{}` would have to be implemented for the type `{}`", - if leading_ellipsis { "..." } else { "" }, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - expected_trait_ref.map(|tr| tr.self_ty()), - ) - } else { - format!( - "{}`{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - expected_trait_ref.map(|tr| tr.self_ty()), - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - }; - - match (has_sub, has_sup) { - (Some(n1), Some(n2)) => { - let _ = write!( - note, - ", for any two lifetimes `'{}` and `'{}`...", - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - ); - } - (Some(n), _) | (_, Some(n)) => { - let _ = write!(note, ", for any lifetime `'{}`...", n,); - } - (None, None) => { - if let Some(n) = expected_has_vid { - let _ = write!(note, ", for some specific lifetime `'{}`...", n,); - } + let passive_voice = match (has_sub, has_sup) { + (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, + (None, None) => { + expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); + match expected_has_vid { + Some(_) => true, + None => any_self_ty_has_vid, } } + }; - note - }); + let (kind, ty_or_sig, trait_path) = if same_self_type { + let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); + self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); + + if self_ty.value.is_closure() + && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) + { + let closure_sig = self_ty.map(|closure| { + if let ty::Closure(_, substs) = closure.kind() { + self.tcx().signature_unclosure( + substs.as_closure().sig(), + rustc_hir::Unsafety::Normal, + ) + } else { + bug!("type is not longer closure"); + } + }); + ( + "signature", + closure_sig.to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + } else { + ( + "other", + self_ty.to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + } + } else if passive_voice { + ( + "passive", + expected_trait_ref.map(|tr| tr.self_ty()).to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + } else { + ( + "other", + expected_trait_ref.map(|tr| tr.self_ty()).to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + }; + + let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) { + (Some(n1), Some(n2)) => ("two", std::cmp::min(n1, n2), std::cmp::max(n1, n2)), + (Some(n), _) | (_, Some(n)) => ("any", n, 0), + (None, None) => { + if let Some(n) = expected_has_vid { + ("some", n, 0) + } else { + ("nothing", 0, 0) + } + } + }; + + let note_1 = ActualImplExplNotes::NoteOne { + leading_ellipsis, + kind, + ty_or_sig, + trait_path, + lt_kind, + lifetime_1, + lifetime_2, + }; let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); - err.note(&{ - let passive_voice = match actual_has_vid { - Some(_) => any_self_ty_has_vid, - None => true, - }; - let mut note = if same_self_type { - format!( - "...but it actually implements `{}`", - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - } else if passive_voice { - format!( - "...but `{}` is actually implemented for the type `{}`", - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - actual_trait_ref.map(|tr| tr.self_ty()), - ) - } else { - format!( - "...but `{}` actually implements `{}`", - actual_trait_ref.map(|tr| tr.self_ty()), - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - }; + let passive_voice = match actual_has_vid { + Some(_) => any_self_ty_has_vid, + None => true, + }; - if let Some(n) = actual_has_vid { - let _ = write!(note, ", for some specific lifetime `'{}`", n); - } + let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); + let kind_2 = if same_self_type { + "implements_trait" + } else if passive_voice { + "implemented_for_ty" + } else { + "ty_implements" + }; - note - }); + let has_lifetime = actual_has_vid.is_some(); + let lifetime = actual_has_vid.unwrap_or_default(); + + let note_2 = + ActualImplExplNotes::NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + + vec![note_1, note_2] } } From 3935a81d473167387123f8d48087f5ee446f92c4 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 13 Sep 2022 20:11:42 +0300 Subject: [PATCH 032/223] Migrate trait_impl_difference.rs --- .../locales/en-US/infer.ftl | 10 +++++ compiler/rustc_infer/src/errors/mod.rs | 38 +++++++++++++++++++ .../trait_impl_difference.rs | 38 ++++++------------- 3 files changed, 60 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index a52ac1339468..d28608cf47de 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -211,3 +211,13 @@ infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not ge .label_satisfy = doesn't satisfy where-clause .label_where = due to a where-clause on `{$def_id}`... .label_dup = implementation of `{$trait_def_id}` is not general enough + +infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature + .found = found `{$found}` + .expected = expected `{$expected}` + .expected_found = expected `{$expected}` + {" "}found `{$found}` + +infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output +infer_tid_consider_borriwing = consider borrowing this type parameter in the trait +infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index f694c5ca4097..e2579ab7b7ce 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -581,3 +581,41 @@ pub struct TraitPlaceholderMismatch { #[subdiagnostic] pub actual_impl_expl_notes: Vec, } + +pub struct ConsiderBorrowingParamHelp { + pub spans: Vec, +} + +impl AddSubdiagnostic for ConsiderBorrowingParamHelp { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut type_param_span: MultiSpan = self.spans.clone().into(); + for &span in &self.spans { + type_param_span.push_span_label(span, fluent::infer::tid_consider_borriwing); + } + diag.span_help(type_param_span, fluent::infer::tid_param_help); + } +} + +#[derive(SessionSubdiagnostic)] +#[help(infer::tid_rel_help)] +pub struct RelationshipHelp; + +#[derive(SessionDiagnostic)] +#[diag(infer::trait_impl_diff)] +pub struct TraitImplDiff { + #[primary_span] + #[label(infer::found)] + pub sp: Span, + #[label(infer::expected)] + pub trait_sp: Span, + #[note(infer::expected_found)] + pub note: (), + #[subdiagnostic] + pub param_help: ConsiderBorrowingParamHelp, + #[subdiagnostic] + // Seems like subdiagnostics are always pushed to the end, so this one + // also has to be a subdiagnostic to maintain order. + pub rel_help: Option, + pub expected: String, + pub found: String, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 5d536e982ed0..bacd8894a0fa 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -1,10 +1,11 @@ //! Error Reporting for `impl` items that do not match the obligations from their `trait`. +use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::Subtype; use crate::traits::ObligationCauseCode::CompareImplItemObligation; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; @@ -51,10 +52,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { trait_def_id: DefId, ) -> ErrorGuaranteed { let trait_sp = self.tcx().def_span(trait_def_id); - let mut err = self - .tcx() - .sess - .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature"); // Mark all unnamed regions in the type with a number. // This diagnostic is called in response to lifetime errors, so be informative. @@ -91,9 +88,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let found = self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; - err.span_label(sp, &format!("found `{}`", found)); - err.span_label(trait_sp, &format!("expected `{}`", expected)); - // Get the span of all the used type parameters in the method. let assoc_item = self.tcx().associated_item(trait_def_id); let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] }; @@ -110,26 +104,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } _ => {} } - let mut type_param_span: MultiSpan = visitor.types.to_vec().into(); - for &span in &visitor.types { - type_param_span - .push_span_label(span, "consider borrowing this type parameter in the trait"); - } - err.note(&format!("expected `{}`\n found `{}`", expected, found)); + let diag = TraitImplDiff { + sp, + trait_sp, + note: (), + param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() }, + rel_help: visitor.types.is_empty().then_some(RelationshipHelp), + expected, + found, + }; - err.span_help( - type_param_span, - "the lifetime requirements from the `impl` do not correspond to the requirements in \ - the `trait`", - ); - if visitor.types.is_empty() { - err.help( - "verify the lifetime relationships in the `trait` and `impl` between the `self` \ - argument, the other inputs and its output", - ); - } - err.emit() + self.tcx().sess.emit_err(diag) } } From 0634b0119cadbf4fcc90d8a399b1c46e1442a5b5 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sat, 17 Sep 2022 02:54:59 +0300 Subject: [PATCH 033/223] Partial work on static_impl_trait.rs --- .../locales/en-US/infer.ftl | 52 +++++ compiler/rustc_infer/src/errors/mod.rs | 97 ++++++++++ .../nice_region_error/static_impl_trait.rs | 183 +++++++----------- 3 files changed, 221 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index d28608cf47de..7a10f4b7bc54 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -221,3 +221,55 @@ infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signatu infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output infer_tid_consider_borriwing = consider borrowing this type parameter in the trait infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + +infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement +infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement +infer_dtcs_has_req_note = the used `impl` has a `'static` requirement +infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement + +infer_but_calling_introduces = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement + .label1 = {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` + } + .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [named] `impl` of `{$impl_path}` + *[anon] inherent `impl` + } + +infer_but_needs_to_satisfy = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement + .influencer = this data with {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` + }... + .require = {$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + } + .used_here = ...is used here... + .introduced_by_bound = 'static` lifetime requirement introduced by this bound + +infer_more_targeted = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but calling `{$ident}` introduces an implicit `'static` lifetime requirement + +infer_ril_introduced_here = `'static` requirement introduced here +infer_ril_introduced_by = requirement introduced by this return type +infer_ril_because_of = because of this returned expression +infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index e2579ab7b7ce..dc79c725951b 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -8,6 +8,7 @@ use rustc_hir::{FnRetTy, Ty}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{Region, TyCtxt}; use rustc_span::symbol::kw; +use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; use crate::infer::error_reporting::{ @@ -619,3 +620,99 @@ pub struct TraitImplDiff { pub expected: String, pub found: String, } + +pub struct DynTraitConstraintSuggestion { + pub span: Span, + pub ident: Ident, +} + +impl AddSubdiagnostic for DynTraitConstraintSuggestion { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut multi_span: MultiSpan = vec![self.span].into(); + multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); + multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); + diag.span_note(multi_span, fluent::infer::dtcs_has_req_note); + diag.span_suggestion_verbose( + self.span.shrink_to_hi(), + fluent::infer::dtcs_suggestion, + " + '_", + Applicability::MaybeIncorrect, + ); + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::but_calling_introduces, code = "E0772")] +pub struct ButCallingIntroduces { + #[label(infer::label1)] + pub param_ty_span: Span, + #[primary_span] + #[label(infer::label2)] + pub cause_span: Span, + + pub has_param_name: bool, + pub param_name: String, + pub has_lifetime: bool, + pub lifetime: String, + pub assoc_item: Symbol, + pub has_impl_path: bool, + pub impl_path: String, +} + +pub struct ReqIntroducedLocations { + pub span: MultiSpan, + pub spans: Vec, + pub fn_decl_span: Span, + pub cause_span: Span, + pub add_label: bool, +} + +impl AddSubdiagnostic for ReqIntroducedLocations { + fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { + for sp in self.spans { + self.span.push_span_label(sp, fluent::infer::ril_introduced_here); + } + + if self.add_label { + self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); + } + self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); + diag.span_note(self.span, fluent::infer::ril_static_introduced_by); + } +} + +pub struct MoreTargeted { + pub ident: Symbol, +} + +impl AddSubdiagnostic for MoreTargeted { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + diag.code(rustc_errors::error_code!(E0772)); + diag.set_primary_message(fluent::infer::more_targeted); + diag.set_arg("ident", self.ident); + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::but_needs_to_satisfy, code = "E0759")] +pub struct ButNeedsToSatisfy { + #[primary_span] + pub sp: Span, + #[label(infer::influencer)] + pub influencer_point: Span, + #[label(infer::used_here)] + pub spans: Vec, + #[label(infer::require)] + pub require_span_as_label: Option, + #[note(infer::require)] + pub require_span_as_note: Option, + #[note(infer::introduced_by_bound)] + pub bound: Option, + + #[subdiagnostic] + pub req_introduces_loc: Option, + + pub spans_empty: bool, + pub has_lifetime: bool, + pub lifetime: String, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9bd2202d2601..b76f7e7689ff 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -1,11 +1,15 @@ //! Error Reporting for static impl Traits. +use crate::errors::{ + ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted, + ReqIntroducedLocations, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{AddSubdiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; @@ -49,46 +53,33 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } let param = self.find_param_with_region(*sup_r, *sub_r)?; - let lifetime = if sup_r.has_name() { - format!("lifetime `{}`", sup_r) - } else { - "an anonymous lifetime `'_`".to_string() + let simple_ident = param.param.pat.simple_ident(); + + let (has_impl_path, impl_path) = match ctxt.assoc_item.container { + AssocItemContainer::TraitContainer => { + let id = ctxt.assoc_item.container_id(tcx); + (true, tcx.def_path_str(id)) + } + AssocItemContainer::ImplContainer => (false, String::new()), }; - let mut err = struct_span_err!( - tcx.sess, - cause.span, - E0772, - "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ - requirement", - param - .param - .pat - .simple_ident() - .map(|s| format!("`{}`", s)) - .unwrap_or_else(|| "`fn` parameter".to_string()), - lifetime, - ctxt.assoc_item.name, - ); - err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); - err.span_label( - cause.span, - &format!( - "...is used and required to live as long as `'static` here \ - because of an implicit lifetime bound on the {}", - match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer => { - let id = ctxt.assoc_item.container_id(tcx); - format!("`impl` of `{}`", tcx.def_path_str(id)) - } - AssocItemContainer::ImplContainer => "inherent `impl`".to_string(), - }, - ), - ); + + let diag = ButCallingIntroduces { + param_ty_span: param.param_ty_span, + cause_span: cause.span, + has_param_name: simple_ident.is_some(), + param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(), + has_lifetime: sup_r.has_name(), + lifetime: sup_r.to_string(), + assoc_item: ctxt.assoc_item.name, + has_impl_path, + impl_path, + }; + let mut err = self.tcx().sess.create_err(diag); if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { let reported = err.emit(); return Some(reported); } else { - err.cancel(); + err.cancel() } } return None; @@ -104,25 +95,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sp = var_origin.span(); let return_sp = sub_origin.span(); let param = self.find_param_with_region(*sup_r, *sub_r)?; - let (lifetime_name, lifetime) = if sup_r.has_name() { - (sup_r.to_string(), format!("lifetime `{}`", sup_r)) - } else { - ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) - }; - let param_name = param - .param - .pat - .simple_ident() - .map(|s| format!("`{}`", s)) - .unwrap_or_else(|| "`fn` parameter".to_string()); - let mut err = struct_span_err!( - tcx.sess, - sp, - E0759, - "{} has {} but it needs to satisfy a `'static` lifetime requirement", - param_name, - lifetime, - ); + let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; let (mention_influencer, influencer_point) = if sup_origin.span().overlaps(param.param_ty_span) { @@ -141,7 +114,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } else { (!sup_origin.span().overlaps(return_sp), param.param_ty_span) }; - err.span_label(influencer_point, &format!("this data with {}...", lifetime)); debug!("try_report_static_impl_trait: param_info={:?}", param); @@ -155,31 +127,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { spans.dedup_by_key(|span| (span.lo(), span.hi())); // We try to make the output have fewer overlapping spans if possible. - let require_msg = if spans.is_empty() { - "...is used and required to live as long as `'static` here" - } else { - "...and is required to live as long as `'static` here" - }; let require_span = if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp }; - for span in &spans { - err.span_label(*span, "...is used here..."); - } - - if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) { - // If any of the "captured here" labels appears on the same line or after - // `require_span`, we put it on a note to ensure the text flows by appearing - // always at the end. - err.span_note(require_span, require_msg); + let spans_empty = spans.is_empty(); + let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp); + let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { + Some(*bound) } else { - // We don't need a note, it's already at the end, it can be shown as a `span_label`. - err.span_label(require_span, require_msg); - } + None + }; + + let mut subdiag = None; - if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { - err.span_note(*bound, "`'static` lifetime requirement introduced by this bound"); - } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { if let ObligationCauseCode::ReturnValue(hir_id) | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() @@ -187,33 +147,50 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let parent_id = tcx.hir().get_parent_item(*hir_id); if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); + let mut spans = Vec::new(); let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); v.visit_ty(ty); if !v.0.is_empty() { span = v.0.clone().into(); - for sp in v.0 { - span.push_span_label(sp, "`'static` requirement introduced here"); - } + spans = v.0; add_label = false; } } - if add_label { - span.push_span_label( - fn_decl.output.span(), - "requirement introduced by this return type", - ); - } - span.push_span_label(cause.span, "because of this returned expression"); - err.span_note( + let fn_decl_span = fn_decl.output.span(); + + subdiag = Some(ReqIntroducedLocations { span, - "`'static` lifetime requirement introduced by the return type", - ); + spans, + fn_decl_span, + cause_span: cause.span, + add_label, + }); } } } + let diag = ButNeedsToSatisfy { + sp, + influencer_point, + spans: spans.clone(), + // If any of the "captured here" labels appears on the same line or after + // `require_span`, we put it on a note to ensure the text flows by appearing + // always at the end. + require_span_as_note: require_as_note.then_some(require_span), + // We don't need a note, it's already at the end, it can be shown as a `span_label`. + require_span_as_label: (!require_as_note).then_some(require_span), + req_introduces_loc: subdiag, + + has_lifetime: sup_r.has_name(), + lifetime: sup_r.to_string(), + spans_empty, + bound, + }; + + let mut err = self.tcx().sess.create_err(diag); + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let mut override_error_code = None; @@ -247,12 +224,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { // Provide a more targeted error code and description. - err.code(rustc_errors::error_code!(E0772)); - err.set_primary_message(&format!( - "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ - requirement", - param_name, lifetime, ident, - )); + let retarget_subdiag = MoreTargeted { ident }; + retarget_subdiag.add_to_diagnostic(&mut err); } let arg = match param.param.pat.simple_ident() { @@ -513,21 +486,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); hir_v.visit_ty(&self_ty); - for span in &traits { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span - .push_span_label(*span, "this has an implicit `'static` lifetime requirement"); - multi_span.push_span_label( - ident.span, - "calling this method introduces the `impl`'s 'static` requirement", - ); - err.span_note(multi_span, "the used `impl` has a `'static` requirement"); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_", - Applicability::MaybeIncorrect, - ); + for &span in &traits { + let subdiag = DynTraitConstraintSuggestion { span, ident }; + subdiag.add_to_diagnostic(err); suggested = true; } } From 57fdd196aeda1e0fa5829248bd4afb8e6f06d7e5 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 22 Sep 2022 17:29:21 +0300 Subject: [PATCH 034/223] Rebase and fix --- compiler/rustc_infer/src/errors/mod.rs | 26 +++++++++---------- .../nice_region_error/static_impl_trait.rs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index dc79c725951b..55df63075d22 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -4,9 +4,9 @@ use rustc_errors::{ MultiSpan, SubdiagnosticMessage, }; use rustc_hir as hir; -use rustc_hir::{FnRetTy, Ty}; +use rustc_hir::FnRetTy; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{Region, TyCtxt}; +use rustc_middle::ty::{Region, Ty, TyCtxt}; use rustc_span::symbol::kw; use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; @@ -522,7 +522,7 @@ pub struct MismatchedStaticLifetime<'a> { pub implicit_static_lifetimes: Vec, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::explicit_lifetime_required, code = "E0621")] pub struct ExplicitLifetimeRequired<'a> { #[primary_span] @@ -542,7 +542,7 @@ pub struct ExplicitLifetimeRequired<'a> { pub new_ty: Ty<'a>, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum ActualImplExplNotes { // Field names have to be different across all variants #[note(infer::actual_impl_expl_1)] @@ -565,7 +565,7 @@ pub enum ActualImplExplNotes { }, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::trait_placeholder_mismatch)] pub struct TraitPlaceholderMismatch { #[primary_span] @@ -587,7 +587,7 @@ pub struct ConsiderBorrowingParamHelp { pub spans: Vec, } -impl AddSubdiagnostic for ConsiderBorrowingParamHelp { +impl AddToDiagnostic for ConsiderBorrowingParamHelp { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { @@ -597,11 +597,11 @@ impl AddSubdiagnostic for ConsiderBorrowingParamHelp { } } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] #[help(infer::tid_rel_help)] pub struct RelationshipHelp; -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::trait_impl_diff)] pub struct TraitImplDiff { #[primary_span] @@ -626,7 +626,7 @@ pub struct DynTraitConstraintSuggestion { pub ident: Ident, } -impl AddSubdiagnostic for DynTraitConstraintSuggestion { +impl AddToDiagnostic for DynTraitConstraintSuggestion { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); @@ -641,7 +641,7 @@ impl AddSubdiagnostic for DynTraitConstraintSuggestion { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::but_calling_introduces, code = "E0772")] pub struct ButCallingIntroduces { #[label(infer::label1)] @@ -667,7 +667,7 @@ pub struct ReqIntroducedLocations { pub add_label: bool, } -impl AddSubdiagnostic for ReqIntroducedLocations { +impl AddToDiagnostic for ReqIntroducedLocations { fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer::ril_introduced_here); @@ -685,7 +685,7 @@ pub struct MoreTargeted { pub ident: Symbol, } -impl AddSubdiagnostic for MoreTargeted { +impl AddToDiagnostic for MoreTargeted { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { diag.code(rustc_errors::error_code!(E0772)); diag.set_primary_message(fluent::infer::more_targeted); @@ -693,7 +693,7 @@ impl AddSubdiagnostic for MoreTargeted { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::but_needs_to_satisfy, code = "E0759")] pub struct ButNeedsToSatisfy { #[primary_span] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index b76f7e7689ff..fbc71bd7e019 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -9,7 +9,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{AddSubdiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; From 6c19c08140b7c0c5a9f9f9a434036b460167c87d Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 25 Sep 2022 10:55:42 +0300 Subject: [PATCH 035/223] More descriptive names for ActualImplExplNotes variants --- compiler/rustc_error_messages/locales/en-US/infer.ftl | 4 ++-- compiler/rustc_infer/src/errors/mod.rs | 8 ++++---- .../nice_region_error/placeholder_error.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 7a10f4b7bc54..8cfd20c6eda2 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -184,7 +184,7 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id *[param_type] type } -infer_actual_impl_expl_1 = {$leading_ellipsis -> +infer_actual_impl_expl_expected = {$leading_ellipsis -> [true] ... *[false] {""} }{$kind -> @@ -198,7 +198,7 @@ infer_actual_impl_expl_1 = {$leading_ellipsis -> *[nothing] {""} } -infer_actual_impl_expl_2 = {$kind_2 -> +infer_actual_impl_expl_but_actually = {$kind_2 -> [implements_trait] ...but it actually implements `{$trait_path_2}` [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 55df63075d22..edd9eca24cb9 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -545,8 +545,8 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { // Field names have to be different across all variants - #[note(infer::actual_impl_expl_1)] - NoteOne { + #[note(infer::actual_impl_expl_expected)] + Expected { leading_ellipsis: bool, kind: &'static str, ty_or_sig: String, @@ -555,8 +555,8 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_2)] - NoteTwo { + #[note(infer::actual_impl_expl_but_actually)] + ButActually { kind_2: &'static str, trait_path_2: String, has_lifetime: bool, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d9fc2ec243f1..cf1032f70063 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -451,7 +451,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } }; - let note_1 = ActualImplExplNotes::NoteOne { + let note_1 = ActualImplExplNotes::Expected { leading_ellipsis, kind, ty_or_sig, @@ -483,7 +483,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = - ActualImplExplNotes::NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + ActualImplExplNotes::ButActually { kind_2, trait_path_2, ty, has_lifetime, lifetime }; vec![note_1, note_2] } From 71d24da665c122fe885d0f62917c01b7f8e8d77f Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 29 Sep 2022 17:10:43 +0300 Subject: [PATCH 036/223] Split into several messages --- .../locales/en-US/infer.ftl | 71 ++++++-- compiler/rustc_infer/src/errors/mod.rs | 168 +++++++++++++++++- .../nice_region_error/placeholder_error.rs | 58 +++--- 3 files changed, 250 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 8cfd20c6eda2..4a43d150968f 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -184,25 +184,64 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id *[param_type] type } -infer_actual_impl_expl_expected = {$leading_ellipsis -> +infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> [true] ... *[false] {""} -}{$kind -> - [signature] closure with signature `{$ty_or_sig}` must implement `{$trait_path}` - [passive] `{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` - *[other] `{$ty_or_sig}` must implement `{$trait_path}` -}{$lt_kind -> - [two] , for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... - [any] , for any lifetime `'{$lifetime_1}`... - [some] , for some specific lifetime `'{lifetime_1}`... - *[nothing] {""} -} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` +infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` +infer_actual_impl_expl_expected_other_two = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_other_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_other_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}` -infer_actual_impl_expl_but_actually = {$kind_2 -> - [implements_trait] ...but it actually implements `{$trait_path_2}` - [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` - *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` -}{$has_lifetime -> +infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path_2}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} +infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path_2}` is actually implemented for the type `{$ty}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} +infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path_2}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index edd9eca24cb9..69fc3be2bc3a 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -544,25 +544,177 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - // Field names have to be different across all variants - #[note(infer::actual_impl_expl_expected)] - Expected { + // Field names have to be different across Expected* and ButActually variants + #[note(infer::actual_impl_expl_expected_signature_two)] + ExpectedSignatureTwo { leading_ellipsis: bool, - kind: &'static str, ty_or_sig: String, trait_path: String, - lt_kind: &'static str, lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_but_actually)] - ButActually { - kind_2: &'static str, + #[note(infer::actual_impl_expl_expected_signature_any)] + ExpectedSignatureAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_some)] + ExpectedSignatureSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_nothing)] + ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_passive_two)] + ExpectedPassiveTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_any)] + ExpectedPassiveAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_some)] + ExpectedPassiveSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_nothing)] + ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_other_two)] + ExpectedOtherTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_other_any)] + ExpectedOtherAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_some)] + ExpectedOtherSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_nothing)] + ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_but_actually_implements_trait)] + ButActuallyImplementsTrait { trait_path_2: String, has_lifetime: bool, lifetime: usize }, + #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] + ButActuallyImplementedForTy { trait_path_2: String, has_lifetime: bool, lifetime: usize, ty: String, }, + #[note(infer::actual_impl_expl_but_actually_ty_implements)] + ButActuallyTyImplements { + trait_path_2: String, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, +} + +pub enum ActualImplExpectedKind { + Signature, + Passive, + Other, +} + +pub enum ActualImplExpectedLifetimeKind { + Two, + Any, + Some, + Nothing, +} + +impl ActualImplExplNotes { + pub fn new_expected( + kind: ActualImplExpectedKind, + lt_kind: ActualImplExpectedLifetimeKind, + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + ) -> Self { + match (kind, lt_kind) { + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedSignatureTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedPassiveTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedOtherTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path } + } + } + } } #[derive(Diagnostic)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index cf1032f70063..d2fd4f6cd7ca 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,4 +1,7 @@ -use crate::errors::{ActualImplExplNotes, TraitPlaceholderMismatch}; +use crate::errors::{ + ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, + TraitPlaceholderMismatch, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; @@ -414,52 +417,54 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } }); ( - "signature", + ActualImplExpectedKind::Signature, closure_sig.to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } else { ( - "other", + ActualImplExpectedKind::Other, self_ty.to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } } else if passive_voice { ( - "passive", + ActualImplExpectedKind::Passive, expected_trait_ref.map(|tr| tr.self_ty()).to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } else { ( - "other", + ActualImplExpectedKind::Other, expected_trait_ref.map(|tr| tr.self_ty()).to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) }; let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) { - (Some(n1), Some(n2)) => ("two", std::cmp::min(n1, n2), std::cmp::max(n1, n2)), - (Some(n), _) | (_, Some(n)) => ("any", n, 0), + (Some(n1), Some(n2)) => { + (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2)) + } + (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0), (None, None) => { if let Some(n) = expected_has_vid { - ("some", n, 0) + (ActualImplExpectedLifetimeKind::Some, n, 0) } else { - ("nothing", 0, 0) + (ActualImplExpectedLifetimeKind::Nothing, 0, 0) } } }; - let note_1 = ActualImplExplNotes::Expected { - leading_ellipsis, + let note_1 = ActualImplExplNotes::new_expected( kind, + lt_kind, + leading_ellipsis, ty_or_sig, trait_path, - lt_kind, lifetime_1, lifetime_2, - }; + ); let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); @@ -471,19 +476,26 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); - let kind_2 = if same_self_type { - "implements_trait" - } else if passive_voice { - "implemented_for_ty" - } else { - "ty_implements" - }; - let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); - let note_2 = - ActualImplExplNotes::ButActually { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + let note_2 = if same_self_type { + ActualImplExplNotes::ButActuallyImplementsTrait { trait_path_2, has_lifetime, lifetime } + } else if passive_voice { + ActualImplExplNotes::ButActuallyImplementedForTy { + trait_path_2, + ty, + has_lifetime, + lifetime, + } + } else { + ActualImplExplNotes::ButActuallyTyImplements { + trait_path_2, + ty, + has_lifetime, + lifetime, + } + }; vec![note_1, note_2] } From eb7ce1703bb719c1d038be6572a349a3e70f7ca2 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Fri, 14 Oct 2022 21:50:06 +0300 Subject: [PATCH 037/223] Use eager translation --- .../locales/en-US/infer.ftl | 2 +- compiler/rustc_infer/src/errors/mod.rs | 38 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 4a43d150968f..4219964a8773 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -258,7 +258,7 @@ infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signatu {" "}found `{$found}` infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -infer_tid_consider_borriwing = consider borrowing this type parameter in the trait +infer_tid_consider_borrowing = consider borrowing this type parameter in the trait infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 69fc3be2bc3a..9092874dfae7 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -544,7 +544,6 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - // Field names have to be different across Expected* and ButActually variants #[note(infer::actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, @@ -731,7 +730,7 @@ pub struct TraitPlaceholderMismatch { pub def_id: String, pub trait_def_id: String, - #[subdiagnostic] + #[subdiagnostic(eager)] pub actual_impl_expl_notes: Vec, } @@ -740,12 +739,17 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { - type_param_span.push_span_label(span, fluent::infer::tid_consider_borriwing); + // Seems like we can't call f() here as Into is required + type_param_span.push_span_label(span, fluent::infer::tid_consider_borrowing); } - diag.span_help(type_param_span, fluent::infer::tid_param_help); + let msg = f(diag, fluent::infer::tid_param_help.into()); + diag.span_help(type_param_span, msg); } } @@ -779,14 +783,19 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); - diag.span_note(multi_span, fluent::infer::dtcs_has_req_note); + let msg = f(diag, fluent::infer::dtcs_has_req_note.into()); + diag.span_note(multi_span, msg); + let msg = f(diag, fluent::infer::dtcs_suggestion.into()); diag.span_suggestion_verbose( self.span.shrink_to_hi(), - fluent::infer::dtcs_suggestion, + msg, " + '_", Applicability::MaybeIncorrect, ); @@ -820,7 +829,10 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { for sp in self.spans { self.span.push_span_label(sp, fluent::infer::ril_introduced_here); } @@ -829,7 +841,8 @@ impl AddToDiagnostic for ReqIntroducedLocations { self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); } self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); - diag.span_note(self.span, fluent::infer::ril_static_introduced_by); + let msg = f(diag, fluent::infer::ril_static_introduced_by.into()); + diag.span_note(self.span, msg); } } @@ -838,7 +851,10 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { diag.code(rustc_errors::error_code!(E0772)); diag.set_primary_message(fluent::infer::more_targeted); diag.set_arg("ident", self.ident); From 40b221814ea00a9d279474188d81b9a063eb3f68 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sat, 15 Oct 2022 13:16:51 +0300 Subject: [PATCH 038/223] Rename subdiagnostic fields that do not need to be unique now --- .../rustc_error_messages/locales/en-US/infer.ftl | 6 +++--- compiler/rustc_infer/src/errors/mod.rs | 11 +++-------- .../nice_region_error/placeholder_error.rs | 13 ++++--------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 4219964a8773..f74af62702e9 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -233,15 +233,15 @@ infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> *[false] {""} }`{$ty_or_sig}` must implement `{$trait_path}` -infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path_2}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } -infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path_2}` is actually implemented for the type `{$ty}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } -infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path_2}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 9092874dfae7..1733b6e148fd 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -617,21 +617,16 @@ pub enum ActualImplExplNotes { #[note(infer::actual_impl_expl_expected_other_nothing)] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, #[note(infer::actual_impl_expl_but_actually_implements_trait)] - ButActuallyImplementsTrait { trait_path_2: String, has_lifetime: bool, lifetime: usize }, + ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { - trait_path_2: String, + trait_path: String, has_lifetime: bool, lifetime: usize, ty: String, }, #[note(infer::actual_impl_expl_but_actually_ty_implements)] - ButActuallyTyImplements { - trait_path_2: String, - has_lifetime: bool, - lifetime: usize, - ty: String, - }, + ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, } pub enum ActualImplExpectedKind { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d2fd4f6cd7ca..904723c4da9d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -474,27 +474,22 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { None => true, }; - let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = if same_self_type { - ActualImplExplNotes::ButActuallyImplementsTrait { trait_path_2, has_lifetime, lifetime } + ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime } } else if passive_voice { ActualImplExplNotes::ButActuallyImplementedForTy { - trait_path_2, + trait_path, ty, has_lifetime, lifetime, } } else { - ActualImplExplNotes::ButActuallyTyImplements { - trait_path_2, - ty, - has_lifetime, - lifetime, - } + ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime } }; vec![note_1, note_2] From 19b8579803979dd3b1e83f7aa9655920eef14b98 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Mon, 24 Oct 2022 19:06:45 +0300 Subject: [PATCH 039/223] Address changes of pr 103345 --- compiler/rustc_infer/src/errors/mod.rs | 92 +++++++++++++------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 1733b6e148fd..51b04eb0df01 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -523,7 +523,7 @@ pub struct MismatchedStaticLifetime<'a> { } #[derive(Diagnostic)] -#[diag(infer::explicit_lifetime_required, code = "E0621")] +#[diag(infer_explicit_lifetime_required, code = "E0621")] pub struct ExplicitLifetimeRequired<'a> { #[primary_span] #[label] @@ -533,7 +533,7 @@ pub struct ExplicitLifetimeRequired<'a> { pub named: String, #[suggestion( - infer::explicit_lifetime_required_sugg, + infer_explicit_lifetime_required_sugg, code = "{new_ty}", applicability = "unspecified" )] @@ -544,7 +544,7 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - #[note(infer::actual_impl_expl_expected_signature_two)] + #[note(infer_actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -552,23 +552,23 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_signature_any)] + #[note(infer_actual_impl_expl_expected_signature_any)] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_signature_some)] + #[note(infer_actual_impl_expl_expected_signature_some)] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_signature_nothing)] + #[note(infer_actual_impl_expl_expected_signature_nothing)] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_expected_passive_two)] + #[note(infer_actual_impl_expl_expected_passive_two)] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -576,23 +576,23 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_passive_any)] + #[note(infer_actual_impl_expl_expected_passive_any)] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_passive_some)] + #[note(infer_actual_impl_expl_expected_passive_some)] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_passive_nothing)] + #[note(infer_actual_impl_expl_expected_passive_nothing)] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_expected_other_two)] + #[note(infer_actual_impl_expl_expected_other_two)] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -600,32 +600,32 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_other_any)] + #[note(infer_actual_impl_expl_expected_other_any)] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_other_some)] + #[note(infer_actual_impl_expl_expected_other_some)] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_other_nothing)] + #[note(infer_actual_impl_expl_expected_other_nothing)] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_but_actually_implements_trait)] + #[note(infer_actual_impl_expl_but_actually_implements_trait)] ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, - #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] + #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(infer::actual_impl_expl_but_actually_ty_implements)] + #[note(infer_actual_impl_expl_but_actually_ty_implements)] ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, } @@ -712,15 +712,15 @@ impl ActualImplExplNotes { } #[derive(Diagnostic)] -#[diag(infer::trait_placeholder_mismatch)] +#[diag(infer_trait_placeholder_mismatch)] pub struct TraitPlaceholderMismatch { #[primary_span] pub span: Span, - #[label(infer::label_satisfy)] + #[label(label_satisfy)] pub satisfy_span: Option, - #[label(infer::label_where)] + #[label(label_where)] pub where_span: Option, - #[label(infer::label_dup)] + #[label(label_dup)] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -741,26 +741,26 @@ impl AddToDiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::infer::tid_consider_borrowing); + type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing); } - let msg = f(diag, fluent::infer::tid_param_help.into()); + let msg = f(diag, fluent::infer_tid_param_help.into()); diag.span_help(type_param_span, msg); } } #[derive(Subdiagnostic)] -#[help(infer::tid_rel_help)] +#[help(infer_tid_rel_help)] pub struct RelationshipHelp; #[derive(Diagnostic)] -#[diag(infer::trait_impl_diff)] +#[diag(infer_trait_impl_diff)] pub struct TraitImplDiff { #[primary_span] - #[label(infer::found)] + #[label(found)] pub sp: Span, - #[label(infer::expected)] + #[label(expected)] pub trait_sp: Span, - #[note(infer::expected_found)] + #[note(expected_found)] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, @@ -783,11 +783,11 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); - multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); - let msg = f(diag, fluent::infer::dtcs_has_req_note.into()); + multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); + multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); + let msg = f(diag, fluent::infer_dtcs_has_req_note.into()); diag.span_note(multi_span, msg); - let msg = f(diag, fluent::infer::dtcs_suggestion.into()); + let msg = f(diag, fluent::infer_dtcs_suggestion.into()); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -798,12 +798,12 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(infer::but_calling_introduces, code = "E0772")] +#[diag(infer_but_calling_introduces, code = "E0772")] pub struct ButCallingIntroduces { - #[label(infer::label1)] + #[label(label1)] pub param_ty_span: Span, #[primary_span] - #[label(infer::label2)] + #[label(label2)] pub cause_span: Span, pub has_param_name: bool, @@ -829,14 +829,14 @@ impl AddToDiagnostic for ReqIntroducedLocations { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { for sp in self.spans { - self.span.push_span_label(sp, fluent::infer::ril_introduced_here); + self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); + self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by); } - self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); - let msg = f(diag, fluent::infer::ril_static_introduced_by.into()); + self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of); + let msg = f(diag, fluent::infer_ril_static_introduced_by.into()); diag.span_note(self.span, msg); } } @@ -851,25 +851,25 @@ impl AddToDiagnostic for MoreTargeted { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.code(rustc_errors::error_code!(E0772)); - diag.set_primary_message(fluent::infer::more_targeted); + diag.set_primary_message(fluent::infer_more_targeted); diag.set_arg("ident", self.ident); } } #[derive(Diagnostic)] -#[diag(infer::but_needs_to_satisfy, code = "E0759")] +#[diag(infer_but_needs_to_satisfy, code = "E0759")] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(infer::influencer)] + #[label(influencer)] pub influencer_point: Span, - #[label(infer::used_here)] + #[label(used_here)] pub spans: Vec, - #[label(infer::require)] + #[label(require)] pub require_span_as_label: Option, - #[note(infer::require)] + #[note(require)] pub require_span_as_note: Option, - #[note(infer::introduced_by_bound)] + #[note(introduced_by_bound)] pub bound: Option, #[subdiagnostic] From 7ecd064bbe32419eb473b28cdc8e41dd34f20aa9 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 20:45:14 +0300 Subject: [PATCH 040/223] Split infer_explicit_lifetime_required into several diags --- .../locales/en-US/infer.ftl | 15 +++--- compiler/rustc_infer/src/errors/mod.rs | 49 ++++++++++++------- .../nice_region_error/named_anon_conflict.rs | 23 +++++---- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index f74af62702e9..52babec4f9ea 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -173,16 +173,15 @@ infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement infer_suggest_add_let_for_letchains = consider adding `let` -infer_explicit_lifetime_required = explicit lifetime required in {$ident_kind -> - [ident] the type of `{$simple_ident}` - *[param_type] parameter type -} +infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` .label = lifetime `{$named}` required -infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$ident_kind -> - [ident] the type of `{$simple_ident}` - *[param_type] type -} +infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type + .label = lifetime `{$named}` required + +infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` + +infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> [true] ... diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 51b04eb0df01..9e3def93a6d3 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -523,23 +523,38 @@ pub struct MismatchedStaticLifetime<'a> { } #[derive(Diagnostic)] -#[diag(infer_explicit_lifetime_required, code = "E0621")] -pub struct ExplicitLifetimeRequired<'a> { - #[primary_span] - #[label] - pub span: Span, - pub ident_kind: &'static str, - pub simple_ident: String, - pub named: String, - - #[suggestion( - infer_explicit_lifetime_required_sugg, - code = "{new_ty}", - applicability = "unspecified" - )] - pub new_ty_span: Span, - #[skip_arg] - pub new_ty: Ty<'a>, +pub enum ExplicitLifetimeRequired<'a> { + #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")] + WithIdent { + #[primary_span] + #[label] + span: Span, + simple_ident: Ident, + named: String, + #[suggestion( + infer_explicit_lifetime_required_sugg_with_ident, + code = "{new_ty}", + applicability = "unspecified" + )] + new_ty_span: Span, + #[skip_arg] + new_ty: Ty<'a>, + }, + #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")] + WithParamType { + #[primary_span] + #[label] + span: Span, + named: String, + #[suggestion( + infer_explicit_lifetime_required_sugg_with_param_type, + code = "{new_ty}", + applicability = "unspecified" + )] + new_ty_span: Span, + #[skip_arg] + new_ty: Ty<'a>, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index d7751158902b..4e13ec90228d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -89,18 +89,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { return None; } - - let simple_ident = param.pat.simple_ident(); - let (ident_kind, simple_ident) = match simple_ident { - Some(ident) => ("ident", ident.to_string()), - None => ("param_type", String::new()), - }; - let named = named.to_string(); - - let err = - ExplicitLifetimeRequired { span, ident_kind, simple_ident, named, new_ty_span, new_ty }; - let err = self.tcx().sess.parse_sess.create_err(err); - Some(err) + let err = match param.pat.simple_ident() { + Some(simple_ident) => ExplicitLifetimeRequired::WithIdent { + span, + simple_ident, + named, + new_ty_span, + new_ty, + }, + None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty }, + }; + Some(self.tcx().sess.parse_sess.create_err(err)) } } From 62f9962eafbf4cf1196d256cf6c559ac397261e1 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 21:50:52 +0300 Subject: [PATCH 041/223] Made ty_or_sig and trait_path use their actual types instead of String --- compiler/rustc_infer/src/errors/mod.rs | 101 ++++++++++++------ .../error_reporting/nice_region_error/mod.rs | 2 +- .../nice_region_error/placeholder_error.rs | 92 ++++++++-------- 3 files changed, 118 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 9e3def93a6d3..388ddd09905a 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,16 +1,18 @@ use hir::GenericParamKind; use rustc_errors::{ fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, - MultiSpan, SubdiagnosticMessage, + IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, }; use rustc_hir as hir; use rustc_hir::FnRetTy; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{Region, Ty, TyCtxt}; +use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath; +use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt}; use rustc_span::symbol::kw; use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; +use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted; use crate::infer::error_reporting::{ need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, ObligationCauseAsDiagArg, @@ -557,91 +559,126 @@ pub enum ExplicitLifetimeRequired<'a> { }, } +pub enum TyOrSig<'tcx> { + Ty(Highlighted<'tcx, Ty<'tcx>>), + ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>), +} + +impl IntoDiagnosticArg for TyOrSig<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + match self { + TyOrSig::Ty(ty) => ty.into_diagnostic_arg(), + TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(), + } + } +} + #[derive(Subdiagnostic)] -pub enum ActualImplExplNotes { +pub enum ActualImplExplNotes<'tcx> { #[note(infer_actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_signature_any)] ExpectedSignatureAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_signature_some)] ExpectedSignatureSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_signature_nothing)] - ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedSignatureNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_expected_passive_two)] ExpectedPassiveTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_passive_any)] ExpectedPassiveAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_passive_some)] ExpectedPassiveSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_passive_nothing)] - ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedPassiveNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_expected_other_two)] ExpectedOtherTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_other_any)] ExpectedOtherAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_other_some)] ExpectedOtherSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_other_nothing)] - ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedOtherNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_but_actually_implements_trait)] - ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, + ButActuallyImplementsTrait { + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + has_lifetime: bool, + lifetime: usize, + }, #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { - trait_path: String, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, #[note(infer_actual_impl_expl_but_actually_ty_implements)] - ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, + ButActuallyTyImplements { + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, } pub enum ActualImplExpectedKind { @@ -657,13 +694,13 @@ pub enum ActualImplExpectedLifetimeKind { Nothing, } -impl ActualImplExplNotes { +impl<'tcx> ActualImplExplNotes<'tcx> { pub fn new_expected( kind: ActualImplExpectedKind, lt_kind: ActualImplExpectedLifetimeKind, leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, ) -> Self { @@ -728,7 +765,7 @@ impl ActualImplExplNotes { #[derive(Diagnostic)] #[diag(infer_trait_placeholder_mismatch)] -pub struct TraitPlaceholderMismatch { +pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, #[label(label_satisfy)] @@ -741,7 +778,7 @@ pub struct TraitPlaceholderMismatch { pub trait_def_id: String, #[subdiagnostic(eager)] - pub actual_impl_expl_notes: Vec, + pub actual_impl_expl_notes: Vec>, } pub struct ConsiderBorrowingParamHelp { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 8a0e332f9c70..59fb74eb5437 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -9,7 +9,7 @@ mod different_lifetimes; pub mod find_anon_type; mod mismatched_static_lifetime; mod named_anon_conflict; -mod placeholder_error; +pub(crate) mod placeholder_error; mod placeholder_relation; mod static_impl_trait; mod trait_impl_difference; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 904723c4da9d..2ff2d1926a26 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,6 +1,6 @@ use crate::errors::{ ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, - TraitPlaceholderMismatch, + TraitPlaceholderMismatch, TyOrSig, }; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; @@ -8,7 +8,7 @@ use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::ExpectedFound; @@ -18,6 +18,42 @@ use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt}; use std::fmt; +// HACK(eddyb) maybe move this in a more central location. +#[derive(Copy, Clone)] +pub struct Highlighted<'tcx, T> { + tcx: TyCtxt<'tcx>, + highlight: RegionHighlightMode<'tcx>, + value: T, +} + +impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> +where + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, +{ + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) + } +} + +impl<'tcx, T> Highlighted<'tcx, T> { + fn map(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> { + Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) } + } +} + +impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> +where + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); + printer.region_highlight_mode = self.highlight; + + let s = self.value.print(printer)?.into_buffer(); + f.write_str(&s) + } +} + impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. @@ -328,39 +364,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_has_vid: Option, any_self_ty_has_vid: bool, leading_ellipsis: bool, - ) -> Vec { - // HACK(eddyb) maybe move this in a more central location. - #[derive(Copy, Clone)] - struct Highlighted<'tcx, T> { - tcx: TyCtxt<'tcx>, - highlight: RegionHighlightMode<'tcx>, - value: T, - } - - impl<'tcx, T> Highlighted<'tcx, T> { - fn map(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> { - Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) } - } - } - - impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> - where - T: for<'a> Print< - 'tcx, - FmtPrinter<'a, 'tcx>, - Error = fmt::Error, - Output = FmtPrinter<'a, 'tcx>, - >, - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); - printer.region_highlight_mode = self.highlight; - - let s = self.value.print(printer)?.into_buffer(); - f.write_str(&s) - } - } - + ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: // @@ -418,27 +422,27 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { }); ( ActualImplExpectedKind::Signature, - closure_sig.to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::ClosureSig(closure_sig), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } else { ( ActualImplExpectedKind::Other, - self_ty.to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(self_ty), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } } else if passive_voice { ( ActualImplExpectedKind::Passive, - expected_trait_ref.map(|tr| tr.self_ty()).to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } else { ( ActualImplExpectedKind::Other, - expected_trait_ref.map(|tr| tr.self_ty()).to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; @@ -474,7 +478,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { None => true, }; - let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); From a86173766c113fdde95c2510de5909d4f9469833 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 21:56:15 +0300 Subject: [PATCH 042/223] Fix nits --- .../error_reporting/nice_region_error/placeholder_error.rs | 6 ++---- .../error_reporting/nice_region_error/static_impl_trait.rs | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 2ff2d1926a26..a5e5f9538565 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -333,7 +333,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { leading_ellipsis, ); - let diag = TraitPlaceholderMismatch { + self.tcx().sess.create_err(TraitPlaceholderMismatch { span, satisfy_span, where_span, @@ -341,9 +341,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { def_id, trait_def_id: self.tcx().def_path_str(trait_def_id), actual_impl_expl_notes, - }; - - self.tcx().sess.create_err(diag) + }) } /// Add notes with details about the expected and actual trait refs, with attention to cases diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index fbc71bd7e019..ae3f174c72e6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { AssocItemContainer::ImplContainer => (false, String::new()), }; - let diag = ButCallingIntroduces { + let mut err = self.tcx().sess.create_err(ButCallingIntroduces { param_ty_span: param.param_ty_span, cause_span: cause.span, has_param_name: simple_ident.is_some(), @@ -73,8 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { assoc_item: ctxt.assoc_item.name, has_impl_path, impl_path, - }; - let mut err = self.tcx().sess.create_err(diag); + }); if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { let reported = err.emit(); return Some(reported); From dda3ebad0a2b26ee35e2f4f3d26f529b092edfc4 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Mon, 7 Nov 2022 15:56:52 +0300 Subject: [PATCH 043/223] Fix broken rebase --- .../error_reporting/nice_region_error/static_impl_trait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index ae3f174c72e6..8a6dadf935f4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -8,7 +8,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; From 2a8b17dbc5489ee085cf1587cf3c63a3fd2746aa Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 29 Nov 2022 19:19:26 +0300 Subject: [PATCH 044/223] Fix formatting --- .../error_reporting/nice_region_error/placeholder_error.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index a5e5f9538565..202f39521e96 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -405,8 +405,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); - if self_ty.value.is_closure() - && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) + if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) { let closure_sig = self_ty.map(|closure| { if let ty::Closure(_, substs) = closure.kind() { From 0c50e1f146efc594eb84146c598d577c9f8a27d2 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Wed, 28 Dec 2022 15:24:18 +0300 Subject: [PATCH 045/223] eager is the default now --- compiler/rustc_infer/src/errors/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 388ddd09905a..9cd053694fe4 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -777,7 +777,7 @@ pub struct TraitPlaceholderMismatch<'tcx> { pub def_id: String, pub trait_def_id: String, - #[subdiagnostic(eager)] + #[subdiagnostic] pub actual_impl_expl_notes: Vec>, } From 0b54782cc8261f8e5d6e0b23785ca259a9eef6bf Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:24:10 +0000 Subject: [PATCH 046/223] Don't translate --print native-static-libs output This breaks tools that depend on the prefix --- compiler/rustc_codegen_ssa/src/back/link.rs | 3 ++- compiler/rustc_codegen_ssa/src/errors.rs | 6 ------ compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl | 2 -- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index edde1537b81e..1fbccfd96cf7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1354,7 +1354,8 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { if !lib_args.is_empty() { sess.emit_note(errors::StaticLibraryNativeArtifacts); // Prefix for greppability - sess.emit_note(errors::NativeStaticLibs { arguments: lib_args.join(" ") }); + // Note: This must not be translated as tools are allowed to depend on this exact string. + sess.note_without_error(&format!("native-static-libs: {}", &lib_args.join(" "))); } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 0620000201f0..277612c30fcc 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -444,12 +444,6 @@ pub struct LinkerFileStem; #[diag(codegen_ssa_static_library_native_artifacts)] pub struct StaticLibraryNativeArtifacts; -#[derive(Diagnostic)] -#[diag(codegen_ssa_native_static_libs)] -pub struct NativeStaticLibs { - pub arguments: String, -} - #[derive(Diagnostic)] #[diag(codegen_ssa_link_script_unavailable)] pub struct LinkScriptUnavailable; diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index db4c82b35c77..f97943b9bd74 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -157,8 +157,6 @@ codegen_ssa_linker_file_stem = couldn't extract file stem from specified linker codegen_ssa_static_library_native_artifacts = Link against the following native artifacts when linking against this static library. The order and any duplication can be significant on some platforms. -codegen_ssa_native_static_libs = native-static-libs: {$arguments} - codegen_ssa_link_script_unavailable = can only use link script when linking with GNU-like linker codegen_ssa_link_script_write_failure = failed to write link script to {$path}: {$error} From ed77a61901df19dd452e2414897ad9a99ef08203 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 28 Dec 2022 17:45:06 +0000 Subject: [PATCH 047/223] Explicitly pass in which crate type to use to each_linked_rlib Otherwise we may pick the dependency formats for say a dylib when linking a staticlib. --- compiler/rustc_codegen_ssa/src/back/link.rs | 148 +++++++++---------- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 1fbccfd96cf7..71589e9993b7 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_wrapper_file, METADATA_FILENAME}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip}; +use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind}; use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; @@ -208,16 +208,16 @@ pub fn link_binary<'a>( Ok(()) } +// Crate type is not passed when calculating the dylibs to include for LTO. In that case all +// crate types must use the same dependency formats. pub fn each_linked_rlib( - sess: &Session, info: &CrateInfo, + crate_type: Option, f: &mut dyn FnMut(CrateNum, &Path), ) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); - let mut fmts = None; - let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin); - if lto_active { + let fmts = if crate_type.is_none() { for combination in info.dependency_formats.iter().combinations(2) { let (ty1, list1) = &combination[0]; let (ty2, list2) = &combination[1]; @@ -230,27 +230,20 @@ pub fn each_linked_rlib( }); } } - } + &info.dependency_formats[0].1 + } else { + let fmts = info + .dependency_formats + .iter() + .find_map(|&(ty, ref list)| if Some(ty) == crate_type { Some(list) } else { None }); - for (ty, list) in info.dependency_formats.iter() { - match ty { - CrateType::Executable - | CrateType::Staticlib - | CrateType::Cdylib - | CrateType::ProcMacro => { - fmts = Some(list); - break; - } - CrateType::Dylib if lto_active => { - fmts = Some(list); - break; - } - _ => {} - } - } - let Some(fmts) = fmts else { - return Err(errors::LinkRlibError::MissingFormat); + let Some(fmts) = fmts else { + return Err(errors::LinkRlibError::MissingFormat); + }; + + fmts }; + for &cnum in crates { match fmts.get(cnum.as_usize() - 1) { Some(&Linkage::NotLinked | &Linkage::Dynamic | &Linkage::IncludedFromDylib) => continue, @@ -516,64 +509,71 @@ fn link_staticlib<'a>( )?; let mut all_native_libs = vec![]; - let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| { - let name = codegen_results.crate_info.crate_name[&cnum]; - let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; + let res = each_linked_rlib( + &codegen_results.crate_info, + Some(CrateType::Staticlib), + &mut |cnum, path| { + let name = codegen_results.crate_info.crate_name[&cnum]; + let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; - // Here when we include the rlib into our staticlib we need to make a - // decision whether to include the extra object files along the way. - // These extra object files come from statically included native - // libraries, but they may be cfg'd away with #[link(cfg(..))]. - // - // This unstable feature, though, only needs liblibc to work. The only - // use case there is where musl is statically included in liblibc.rlib, - // so if we don't want the included version we just need to skip it. As - // a result the logic here is that if *any* linked library is cfg'd away - // we just skip all object files. - // - // Clearly this is not sufficient for a general purpose feature, and - // we'd want to read from the library's metadata to determine which - // object files come from where and selectively skip them. - let skip_object_files = native_libs.iter().any(|lib| { - matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. }) - && !relevant_lib(sess, lib) - }); + // Here when we include the rlib into our staticlib we need to make a + // decision whether to include the extra object files along the way. + // These extra object files come from statically included native + // libraries, but they may be cfg'd away with #[link(cfg(..))]. + // + // This unstable feature, though, only needs liblibc to work. The only + // use case there is where musl is statically included in liblibc.rlib, + // so if we don't want the included version we just need to skip it. As + // a result the logic here is that if *any* linked library is cfg'd away + // we just skip all object files. + // + // Clearly this is not sufficient for a general purpose feature, and + // we'd want to read from the library's metadata to determine which + // object files come from where and selectively skip them. + let skip_object_files = native_libs.iter().any(|lib| { + matches!(lib.kind, NativeLibKind::Static { bundle: None | Some(true), .. }) + && !relevant_lib(sess, lib) + }); - let lto = are_upstream_rust_objects_already_included(sess) - && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); + let lto = are_upstream_rust_objects_already_included(sess) + && !ignored_for_lto(sess, &codegen_results.crate_info, cnum); - // Ignoring obj file starting with the crate name - // as simple comparison is not enough - there - // might be also an extra name suffix - let obj_start = name.as_str().to_owned(); + // Ignoring obj file starting with the crate name + // as simple comparison is not enough - there + // might be also an extra name suffix + let obj_start = name.as_str().to_owned(); - ab.add_archive( - path, - Box::new(move |fname: &str| { - // Ignore metadata files, no matter the name. - if fname == METADATA_FILENAME { - return true; - } + ab.add_archive( + path, + Box::new(move |fname: &str| { + // Ignore metadata files, no matter the name. + if fname == METADATA_FILENAME { + return true; + } - // Don't include Rust objects if LTO is enabled - if lto && looks_like_rust_object_file(fname) { - return true; - } + // Don't include Rust objects if LTO is enabled + if lto && looks_like_rust_object_file(fname) { + return true; + } - // Otherwise if this is *not* a rust object and we're skipping - // objects then skip this file - if skip_object_files && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) { - return true; - } + // Otherwise if this is *not* a rust object and we're skipping + // objects then skip this file + if skip_object_files + && (!fname.starts_with(&obj_start) || !fname.ends_with(".o")) + { + return true; + } - // ok, don't skip this - false - }), - ) - .unwrap(); + // ok, don't skip this + false + }), + ) + .unwrap(); - all_native_libs.extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); - }); + all_native_libs + .extend(codegen_results.crate_info.native_libraries[&cnum].iter().cloned()); + }, + ); if let Err(e) = res { sess.emit_fatal(e); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 1a7de1a184a9..7aadcdd22287 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1002,7 +1002,7 @@ fn start_executing_work( let sess = tcx.sess; let mut each_linked_rlib_for_lto = Vec::new(); - drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { + drop(link::each_linked_rlib(crate_info, None, &mut |cnum, path| { if link::ignored_for_lto(sess, crate_info, cnum) { return; } From 520b5fac10eb9f7c096e0b6ca8e92b30eacba619 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 26 Dec 2022 04:19:27 +0000 Subject: [PATCH 048/223] Rework hir Bounds collection --- .../rustc_hir_analysis/src/astconv/mod.rs | 93 +++++++++++++------ compiler/rustc_hir_analysis/src/bounds.rs | 93 ++++++++----------- .../src/collect/item_bounds.rs | 10 +- .../src/collect/predicates_of.rs | 9 +- compiler/rustc_privacy/src/lib.rs | 29 +++--- 5 files changed, 127 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6f0c5d36a5f5..5d38f9eaafae 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -682,7 +682,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Binder::bind_with_vars(tcx.mk_trait_ref(trait_def_id, substs), bound_vars); debug!(?poly_trait_ref, ?assoc_bindings); - bounds.trait_bounds.push((poly_trait_ref, span, constness)); + bounds.push_trait_bound(tcx, poly_trait_ref, span, constness); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { @@ -853,18 +853,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Sets `implicitly_sized` to true on `Bounds` if necessary - pub(crate) fn add_implicitly_sized<'hir>( + pub(crate) fn add_implicitly_sized( &self, - bounds: &mut Bounds<'hir>, - ast_bounds: &'hir [hir::GenericBound<'hir>], - self_ty_where_predicates: Option<(LocalDefId, &'hir [hir::WherePredicate<'hir>])>, + bounds: &mut Bounds<'tcx>, + self_ty: Ty<'tcx>, + ast_bounds: &'tcx [hir::GenericBound<'tcx>], + self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, ) { let tcx = self.tcx(); // Try to find an unbound in bounds. let mut unbound = None; - let mut search_bounds = |ast_bounds: &'hir [hir::GenericBound<'hir>]| { + let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { for ab in ast_bounds { if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { if unbound.is_none() { @@ -912,7 +913,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // No lang item for `Sized`, so we can't add it as a bound. return; } - bounds.implicitly_sized = Some(span); + bounds.push_sized(tcx, self_ty, span); } /// This helper takes a *converted* parameter type (`param_ty`) @@ -963,10 +964,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } hir::GenericBound::Outlives(lifetime) => { let region = self.ast_region_to_region(lifetime, None); - bounds.region_bounds.push(( - ty::Binder::bind_with_vars(region, bound_vars), + bounds.push_region_bound( + self.tcx(), + ty::Binder::bind_with_vars( + ty::OutlivesPredicate(param_ty, region), + bound_vars, + ), lifetime.ident.span, - )); + ); } } } @@ -1225,13 +1230,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; } } - bounds.projection_bounds.push(( - projection_ty.map_bound(|projection_ty| ty::ProjectionPredicate { - projection_ty, - term: term, - }), + bounds.push_projection_bound( + tcx, + projection_ty + .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), binding.span, - )); + ); } ConvertedBindingKind::Constraint(ast_bounds) => { // "Desugar" a constraint like `T: Iterator` to @@ -1260,7 +1264,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn conv_object_ty_poly_trait_ref( &self, span: Span, - trait_bounds: &[hir::PolyTraitRef<'_>], + hir_trait_bounds: &[hir::PolyTraitRef<'_>], lifetime: &hir::Lifetime, borrowed: bool, representation: DynKind, @@ -1270,7 +1274,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; - for trait_bound in trait_bounds.iter().rev() { + for trait_bound in hir_trait_bounds.iter().rev() { if let GenericArgCountResult { correct: Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }), @@ -1287,10 +1291,45 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + let mut trait_bounds = vec![]; + let mut projection_bounds = vec![]; + for (pred, span) in bounds.predicates() { + let bound_pred = pred.kind(); + match bound_pred.skip_binder() { + ty::PredicateKind::Clause(clause) => match clause { + ty::Clause::Trait(trait_pred) => { + assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); + trait_bounds.push(( + bound_pred.rebind(trait_pred.trait_ref), + span, + trait_pred.constness, + )); + } + ty::Clause::Projection(proj) => { + projection_bounds.push((bound_pred.rebind(proj), span)); + } + ty::Clause::TypeOutlives(_) => { + // Do nothing, we deal with regions separately + } + ty::Clause::RegionOutlives(_) => bug!(), + }, + ty::PredicateKind::WellFormed(_) + | ty::PredicateKind::ObjectSafe(_) + | ty::PredicateKind::ClosureKind(_, _, _) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::ConstEvaluatable(_) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::TypeWellFormedFromEnv(_) + | ty::PredicateKind::Ambiguous => bug!(), + } + } + // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. let expanded_traits = - traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().map(|&(a, b, _)| (a, b))); + traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b, _)| (a, b))); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); @@ -1327,8 +1366,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } if regular_traits.is_empty() && auto_traits.is_empty() { - let trait_alias_span = bounds - .trait_bounds + let trait_alias_span = trait_bounds .iter() .map(|&(trait_ref, _, _)| trait_ref.def_id()) .find(|&trait_ref| tcx.is_trait_alias(trait_ref)) @@ -1359,8 +1397,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Use a `BTreeSet` to keep output in a more consistent order. let mut associated_types: FxHashMap> = FxHashMap::default(); - let regular_traits_refs_spans = bounds - .trait_bounds + let regular_traits_refs_spans = trait_bounds .into_iter() .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); @@ -1414,7 +1451,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - bounds.projection_bounds.push((pred, span)); + projection_bounds.push((pred, span)); } } _ => (), @@ -1422,7 +1459,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - for (projection_bound, _) in &bounds.projection_bounds { + for (projection_bound, _) in &projection_bounds { for def_ids in associated_types.values_mut() { def_ids.remove(&projection_bound.projection_def_id()); } @@ -1431,7 +1468,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.complain_about_missing_associated_types( associated_types, potential_assoc_types, - trait_bounds, + hir_trait_bounds, ); // De-duplicate auto traits so that, e.g., `dyn Trait + Send + Send` is the same as @@ -1473,7 +1510,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let substs = tcx.intern_substs(&substs[..]); let span = i.bottom().1; - let empty_generic_args = trait_bounds.iter().any(|hir_bound| { + let empty_generic_args = hir_trait_bounds.iter().any(|hir_bound| { hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id) && hir_bound.span.contains(span) }); @@ -1505,7 +1542,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { + let existential_projections = projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|mut b| { assert_eq!(b.projection_ty.self_ty(), dummy_self); diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 3e3544ce666e..0880c8c15f2e 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -1,6 +1,7 @@ //! Bounds are restrictions applied to some types after they've been converted into the //! `ty` form from the HIR. +use rustc_hir::LangItem; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; @@ -15,73 +16,53 @@ use rustc_span::Span; /// ^^^^^^^^^ bounding the type parameter `T` /// /// impl dyn Bar + Baz -/// ^^^^^^^^^ bounding the forgotten dynamic type +/// ^^^^^^^^^ bounding the type-erased dynamic type /// ``` /// /// Our representation is a bit mixed here -- in some cases, we /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - /// A list of region bounds on the (implicit) self type. So if you - /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but - /// the `T` is not explicitly included). - pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>, - - /// A list of trait bounds. So if you had `T: Debug` this would be - /// `T: Debug`. Note that the self-type is explicit here. - pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>, - - /// A list of projection equality bounds. So if you had `T: - /// Iterator` this would include `::Item => u32`. Note that the self-type is explicit - /// here. - pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, - - /// `Some` if there is *no* `?Sized` predicate. The `span` - /// is the location in the source of the `T` declaration which can - /// be cited as the source of the `T: Sized` requirement. - pub implicitly_sized: Option, + pub predicates: Vec<(ty::Predicate<'tcx>, Span)>, } impl<'tcx> Bounds<'tcx> { - /// Converts a bounds list into a flat set of predicates (like - /// where-clauses). Because some of our bounds listings (e.g., - /// regions) don't include the self-type, you must supply the - /// self-type here (the `param_ty` parameter). - pub fn predicates<'out, 's>( - &'s self, + pub fn push_region_bound( + &mut self, tcx: TyCtxt<'tcx>, - param_ty: Ty<'tcx>, - // the output must live shorter than the duration of the borrow of self and 'tcx. - ) -> impl Iterator, Span)> + 'out - where - 'tcx: 'out, - 's: 'out, - { - // If it could be sized, and is, add the `Sized` predicate. - let sized_predicate = self.implicitly_sized.and_then(|span| { - // FIXME: use tcx.at(span).mk_trait_ref(LangItem::Sized) here? This may make no-core code harder to write. - let sized = tcx.lang_items().sized_trait()?; - let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized, [param_ty])); - Some((trait_ref.without_const().to_predicate(tcx), span)) - }); + region: ty::PolyTypeOutlivesPredicate<'tcx>, + span: Span, + ) { + self.predicates.push((region.to_predicate(tcx), span)); + } - let region_preds = self.region_bounds.iter().map(move |&(region_bound, span)| { - let pred = region_bound - .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound)) - .to_predicate(tcx); - (pred, span) - }); - let trait_bounds = - self.trait_bounds.iter().map(move |&(bound_trait_ref, span, constness)| { - let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx); - (predicate, span) - }); - let projection_bounds = self - .projection_bounds - .iter() - .map(move |&(projection, span)| (projection.to_predicate(tcx), span)); + pub fn push_trait_bound( + &mut self, + tcx: TyCtxt<'tcx>, + trait_ref: ty::PolyTraitRef<'tcx>, + span: Span, + constness: ty::BoundConstness, + ) { + self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span)); + } - sized_predicate.into_iter().chain(region_preds).chain(trait_bounds).chain(projection_bounds) + pub fn push_projection_bound( + &mut self, + tcx: TyCtxt<'tcx>, + projection: ty::PolyProjectionPredicate<'tcx>, + span: Span, + ) { + self.predicates.push((projection.to_predicate(tcx), span)); + } + + pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { + let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); + let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty])); + // Preferrable to put this obligation first, since we report better errors for sized ambiguity. + self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span)); + } + + pub fn predicates(&self) -> impl Iterator, Span)> + '_ { + self.predicates.iter().cloned() } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 0542e2c8f508..093e9560ccdf 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -28,7 +28,7 @@ fn associated_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, assoc_item_def_id); let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); // Associated types are implicitly sized unless a `?Sized` bound is found - >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + >::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); let trait_def_id = tcx.parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); @@ -44,9 +44,7 @@ fn associated_type_bounds<'tcx>( } }); - let all_bounds = tcx - .arena - .alloc_from_iter(bounds.predicates(tcx, item_ty).into_iter().chain(bounds_from_parent)); + let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), all_bounds); all_bounds } @@ -74,10 +72,10 @@ fn opaque_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = >::compute_bounds(&icx, item_ty, ast_bounds); // Opaque types are implicitly sized unless a `?Sized` bound is found - >::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span); + >::add_implicitly_sized(&icx, &mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); - tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty)) + tcx.arena.alloc_from_iter(bounds.predicates()) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 0943350e2d47..024b3beada05 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -165,12 +165,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP >::add_implicitly_sized( &icx, &mut bounds, + param_ty, &[], Some((param.def_id, ast_generics.predicates)), param.span, ); trace!(?bounds); - predicates.extend(bounds.predicates(tcx, param_ty)); + predicates.extend(bounds.predicates()); trace!(?predicates); } GenericParamKind::Const { .. } => { @@ -217,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP &mut bounds, bound_vars, ); - predicates.extend(bounds.predicates(tcx, ty)); + predicates.extend(bounds.predicates()); } hir::WherePredicate::RegionPredicate(region_pred) => { @@ -536,7 +537,7 @@ pub(super) fn super_predicates_that_define_assoc_type( >::compute_bounds(&icx, self_param_ty, bounds) }; - let superbounds1 = superbounds1.predicates(tcx, self_param_ty); + let superbounds1 = superbounds1.predicates(); // Convert any explicit superbounds in the where-clause, // e.g., `trait Foo where Self: Bar`. @@ -745,5 +746,5 @@ fn predicates_from_bound<'tcx>( ) -> Vec<(ty::Predicate<'tcx>, Span)> { let mut bounds = Bounds::default(); astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); - bounds.predicates(astconv.tcx(), param_ty).collect() + bounds.predicates().collect() } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 72d38aeac7a0..2438fce606c0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -1223,19 +1223,22 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { self.tcx.types.never, ); - for (trait_predicate, _, _) in bounds.trait_bounds { - if self.visit_trait(trait_predicate.skip_binder()).is_break() { - return; - } - } - - for (poly_predicate, _) in bounds.projection_bounds { - let pred = poly_predicate.skip_binder(); - let poly_pred_term = self.visit(pred.term); - if poly_pred_term.is_break() - || self.visit_projection_ty(pred.projection_ty).is_break() - { - return; + for (pred, _) in bounds.predicates() { + match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { + if self.visit_trait(trait_predicate.trait_ref).is_break() { + return; + } + } + ty::PredicateKind::Clause(ty::Clause::Projection(proj_predicate)) => { + let term = self.visit(proj_predicate.term); + if term.is_break() + || self.visit_projection_ty(proj_predicate.projection_ty).is_break() + { + return; + } + } + _ => {} } } } From 2675848b0a5248afeee552aee0c473bad9b4d9a3 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 30 Dec 2022 16:06:55 +0100 Subject: [PATCH 049/223] Add codegen test for `Box::new(uninit)` of big arrays --- src/test/codegen/box-maybe-uninit-llvm14.rs | 14 +++++++++++--- src/test/codegen/box-maybe-uninit.rs | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/test/codegen/box-maybe-uninit-llvm14.rs b/src/test/codegen/box-maybe-uninit-llvm14.rs index bd1a6599c336..7b5ae894311e 100644 --- a/src/test/codegen/box-maybe-uninit-llvm14.rs +++ b/src/test/codegen/box-maybe-uninit-llvm14.rs @@ -2,7 +2,7 @@ // Once we're done with llvm 14 and earlier, this test can be deleted. -#![crate_type="lib"] +#![crate_type = "lib"] use std::mem::MaybeUninit; @@ -17,8 +17,16 @@ pub fn box_uninitialized() -> Box> { Box::new(MaybeUninit::uninit()) } -// FIXME: add a test for a bigger box. Currently broken, see -// https://github.com/rust-lang/rust/issues/58201. +// https://github.com/rust-lang/rust/issues/58201 +#[no_mangle] +pub fn box_uninitialized2() -> Box> { + // CHECK-LABEL: @box_uninitialized2 + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} // Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above. We don't check the attributes here because we can't rely diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs index e105e26f16a2..c82b56a71f5c 100644 --- a/src/test/codegen/box-maybe-uninit.rs +++ b/src/test/codegen/box-maybe-uninit.rs @@ -1,6 +1,6 @@ // compile-flags: -O // min-llvm-version: 15.0 -#![crate_type="lib"] +#![crate_type = "lib"] use std::mem::MaybeUninit; @@ -15,8 +15,16 @@ pub fn box_uninitialized() -> Box> { Box::new(MaybeUninit::uninit()) } -// FIXME: add a test for a bigger box. Currently broken, see -// https://github.com/rust-lang/rust/issues/58201. +// https://github.com/rust-lang/rust/issues/58201 +#[no_mangle] +pub fn box_uninitialized2() -> Box> { + // CHECK-LABEL: @box_uninitialized2 + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} // Hide the `allocalign` attribute in the declaration of __rust_alloc // from the CHECK-NOT above, and also verify the attributes got set reasonably. From 0047e250909dd4739fcd20e77a49685f45490987 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 30 Dec 2022 13:38:34 +0100 Subject: [PATCH 050/223] Add some docs to `bug`, `span_bug` and `delay_span_bug` --- compiler/rustc_errors/src/lib.rs | 2 ++ compiler/rustc_middle/src/macros.rs | 18 ++++++++++++++++++ compiler/rustc_middle/src/util/bug.rs | 3 +-- compiler/rustc_session/src/session.rs | 14 +++++++++++++- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b03352d5fec6..9ed31d9419ce 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -973,6 +973,7 @@ impl Handler { self.inner.borrow_mut().span_bug(span, msg) } + /// For documentation on this, see `Session::delay_span_bug`. #[track_caller] pub fn delay_span_bug( &self, @@ -1518,6 +1519,7 @@ impl HandlerInner { self.emit_diagnostic(diag.set_span(sp)); } + /// For documentation on this, see `Session::delay_span_bug`. #[track_caller] fn delay_span_bug( &mut self, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index 01fe72de6125..5ca4d260179c 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -1,3 +1,13 @@ +/// A macro for triggering an ICE. +/// Calling `bug` instead of panicking will result in a nicer error message and should +/// therefore be prefered over `panic`/`unreachable` or others. +/// +/// If you have a span available, you should use [`span_bug`] instead. +/// +/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// +/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug +/// [`span_bug`]: crate::span_bug #[macro_export] macro_rules! bug { () => ( $crate::bug!("impossible case reached") ); @@ -8,6 +18,14 @@ macro_rules! bug { }); } +/// A macro for triggering an ICE with a span. +/// Calling `span_bug!` instead of panicking will result in a nicer error message and point +/// at the code the compiler was compiling when it ICEd. This is the preferred way to trigger +/// ICEs. +/// +/// If the bug should only be emitted when compilation didn't fail, [`Session::delay_span_bug`] may be useful. +/// +/// [`Session::delay_span_bug`]: rustc_session::Session::delay_span_bug #[macro_export] macro_rules! span_bug { ($span:expr, $msg:expr) => ({ $crate::util::bug::span_bug_fmt($span, ::std::format_args!($msg)) }); diff --git a/compiler/rustc_middle/src/util/bug.rs b/compiler/rustc_middle/src/util/bug.rs index fd7045d6a03f..b73ae5939053 100644 --- a/compiler/rustc_middle/src/util/bug.rs +++ b/compiler/rustc_middle/src/util/bug.rs @@ -35,8 +35,7 @@ fn opt_span_bug_fmt>( (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg), (None, _) => panic_any(msg), } - }); - unreachable!(); + }) } /// A query to trigger a `delay_span_bug`. Clearly, if one has a `tcx` one can already trigger a diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 4a3d29414d6e..1b2e8d9dc707 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -590,7 +590,19 @@ impl Session { pub fn warn(&self, msg: impl Into) { self.diagnostic().warn(msg) } - /// Delay a span_bug() call until abort_if_errors() + + /// Ensures that compilation cannot succeed. + /// + /// If this function has been called but no errors have been emitted and + /// compilation succeeds, it will cause an internal compiler error (ICE). + /// + /// This can be used in code paths that should never run on successful compilations. + /// For example, it can be used to create an [`ErrorGuaranteed`] + /// (but you should prefer threading through the [`ErrorGuaranteed`] from an error emission directly). + /// + /// If no span is available, use [`DUMMY_SP`]. + /// + /// [`DUMMY_SP`]: rustc_span::DUMMY_SP #[track_caller] pub fn delay_span_bug>( &self, From cc2881391a1f1e01faa2f7ff21a172a15fbbaacd Mon Sep 17 00:00:00 2001 From: gimbles Date: Sat, 31 Dec 2022 15:32:09 +0530 Subject: [PATCH 051/223] Add tidy check for dbg --- library/std/src/macros.rs | 1 + src/tools/tidy/src/style.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs index 6e4ba1404e55..fcc5cfafd808 100644 --- a/library/std/src/macros.rs +++ b/library/std/src/macros.rs @@ -3,6 +3,7 @@ //! This module contains a set of macros which are exported from the standard //! library. Each macro is available for use when linking against the standard //! library. +// ignore-tidy-dbg #[doc = include_str!("../../core/src/macros/panic.md")] #[macro_export] diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index f91e38262f64..f409a86db26c 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -15,6 +15,7 @@ //! //! A number of these checks can be opted-out of with various directives of the form: //! `// ignore-tidy-CHECK-NAME`. +// ignore-tidy-dbg use crate::walk::{filter_dirs, walk}; use regex::{Regex, RegexSet}; @@ -278,6 +279,7 @@ pub fn check(path: &Path, bad: &mut bool) { let mut skip_leading_newlines = contains_ignore_directive(can_contain, &contents, "leading-newlines"); let mut skip_copyright = contains_ignore_directive(can_contain, &contents, "copyright"); + let mut skip_dbg = contains_ignore_directive(can_contain, &contents, "dbg"); let mut leading_new_lines = false; let mut trailing_new_lines = 0; let mut lines = 0; @@ -306,6 +308,21 @@ pub fn check(path: &Path, bad: &mut bool) { let mut err = |msg: &str| { tidy_error!(bad, "{}:{}: {}", file.display(), i + 1, msg); }; + + if trimmed.contains("dbg!") + && !trimmed.starts_with("//") + && !file + .ancestors() + .any(|a| a.ends_with("src/test") || a.ends_with("library/alloc/tests")) + && filename != "tests.rs" + { + suppressible_tidy_err!( + err, + skip_dbg, + "`dbg!` macro is intended as a debugging tool. It should not be in version control." + ) + } + if !under_rustfmt && line.chars().count() > max_columns && !long_line_is_ok(&extension, is_error_code, max_columns, line) From c49555821f9735239bf12281b9151eac3b4596d4 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Thu, 17 Nov 2022 13:21:36 -0700 Subject: [PATCH 052/223] warn when there's a newer version of the x tool available --- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 20 +++++++++++++++++++- src/tools/tidy/src/x.rs | 19 +++++++++++++++++++ src/tools/x/src/main.rs | 8 ++++++++ 4 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/tools/tidy/src/x.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index ce7e7ac5cd4c..bfcf0907365a 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -69,3 +69,4 @@ pub mod ui_tests; pub mod unit_tests; pub mod unstable_book; pub mod walk; +pub mod x; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 6714c63ee62a..f01d4673368e 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -53,6 +53,21 @@ fn main() { VecDeque::with_capacity(concurrency.get()); macro_rules! check { + ($p:ident) => { + while handles.len() >= concurrency.get() { + handles.pop_front().unwrap().join().unwrap(); + } + + let handle = s.spawn(|| { + let mut flag = false; + $p::check(&mut flag); + if (flag) { + bad.store(true, Ordering::Relaxed); + } + }); + handles.push_back(handle); + }; + ($p:ident $(, $args:expr)* ) => { drain_handles(&mut handles); @@ -64,7 +79,8 @@ fn main() { } }); handles.push_back(handle); - } + }; + } check!(target_specific_tests, &src_path); @@ -107,6 +123,8 @@ fn main() { check!(alphabetical, &compiler_path); check!(alphabetical, &library_path); + check!(x); + let collected = { drain_handles(&mut handles); diff --git a/src/tools/tidy/src/x.rs b/src/tools/tidy/src/x.rs new file mode 100644 index 000000000000..2cbbde8de824 --- /dev/null +++ b/src/tools/tidy/src/x.rs @@ -0,0 +1,19 @@ +use std::process::Command; + +pub fn check(_bad: &mut bool) { + let result = Command::new("x") + .arg("--version") + .output(); + let output = match result { + Ok(output) => output, + Err(_e) => todo!(), + }; + + if output.status.success() { + let version = String::from_utf8_lossy(&output.stdout); + assert_eq!("0.1.0", version.trim_end()); + } + // FIXME: throw some kind of tidy error when the version of x isn't + // greater than or equal to the version we'd expect. + //tidy_error!(bad, "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`") +} diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index f07ff43efe98..db5d03710d76 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -52,6 +52,14 @@ fn exec_or_status(command: &mut Command) -> io::Result { } fn main() { + match env::args().skip(1).next().as_deref() { + Some("--version") => { + let version = env!("CARGO_PKG_VERSION"); + println!("{}", version); + return; + } + _ => {} + } let current = match env::current_dir() { Ok(dir) => dir, Err(err) => { From b2cd3374e9a7ed637b1b5f1a85cb92a7928d712d Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 28 Nov 2022 16:08:00 -0700 Subject: [PATCH 053/223] remove leading comma from macro expansion --- src/bootstrap/bootstrap.py | 4 ++-- src/tools/tidy/src/lib.rs | 2 +- src/tools/tidy/src/main.rs | 22 +++------------------- src/tools/tidy/src/{x.rs => x_version.rs} | 4 +--- 4 files changed, 7 insertions(+), 25 deletions(-) rename src/tools/tidy/src/{x.rs => x_version.rs} (88%) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9cf43fc7a219..d7ba015982a4 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -934,8 +934,8 @@ def main(): if len(sys.argv) > 1 and sys.argv[1] == 'help': sys.argv = [sys.argv[0], '-h'] + sys.argv[2:] - help_triggered = ( - '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) + # help_triggered = ('-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) + help_triggered = len(sys.argv) == 1 or any(x in ["-h", "--help", "--version"] for x in sys.argv) try: bootstrap(help_triggered) if not help_triggered: diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index bfcf0907365a..4075f2616b0f 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -69,4 +69,4 @@ pub mod ui_tests; pub mod unit_tests; pub mod unstable_book; pub mod walk; -pub mod x; +pub mod x_version; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index f01d4673368e..56fcc561a3f8 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -53,34 +53,18 @@ fn main() { VecDeque::with_capacity(concurrency.get()); macro_rules! check { - ($p:ident) => { - while handles.len() >= concurrency.get() { - handles.pop_front().unwrap().join().unwrap(); - } - - let handle = s.spawn(|| { - let mut flag = false; - $p::check(&mut flag); - if (flag) { - bad.store(true, Ordering::Relaxed); - } - }); - handles.push_back(handle); - }; - ($p:ident $(, $args:expr)* ) => { drain_handles(&mut handles); let handle = s.spawn(|| { let mut flag = false; - $p::check($($args),* , &mut flag); + $p::check($($args, )* &mut flag); if (flag) { bad.store(true, Ordering::Relaxed); } }); handles.push_back(handle); - }; - + } } check!(target_specific_tests, &src_path); @@ -123,7 +107,7 @@ fn main() { check!(alphabetical, &compiler_path); check!(alphabetical, &library_path); - check!(x); + check!(x_version); let collected = { drain_handles(&mut handles); diff --git a/src/tools/tidy/src/x.rs b/src/tools/tidy/src/x_version.rs similarity index 88% rename from src/tools/tidy/src/x.rs rename to src/tools/tidy/src/x_version.rs index 2cbbde8de824..148f97176f96 100644 --- a/src/tools/tidy/src/x.rs +++ b/src/tools/tidy/src/x_version.rs @@ -1,9 +1,7 @@ use std::process::Command; pub fn check(_bad: &mut bool) { - let result = Command::new("x") - .arg("--version") - .output(); + let result = Command::new("x").arg("--version").output(); let output = match result { Ok(output) => output, Err(_e) => todo!(), From b9b33d983d83fde3067a28fdd126fd84061e74c8 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 5 Dec 2022 16:18:43 -0700 Subject: [PATCH 054/223] spawn x command and compare semvers --- Cargo.lock | 5 +++-- src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/x_version.rs | 39 ++++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f99e58e59b8e..8cafdc83d4f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4805,9 +4805,9 @@ checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" [[package]] name = "semver" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] @@ -5309,6 +5309,7 @@ dependencies = [ "lazy_static", "miropt-test-tools", "regex", + "semver", "termcolor", "walkdir", ] diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index fff83a1d097b..5f5ae3a65efa 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -11,6 +11,7 @@ miropt-test-tools = { path = "../miropt-test-tools" } lazy_static = "1" walkdir = "2" ignore = "0.4.18" +semver = "1.0.14" termcolor = "1.1.3" [[bin]] diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 148f97176f96..bbb2662bdcf6 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -1,17 +1,36 @@ -use std::process::Command; +use semver::{BuildMetadata, Prerelease, Version}; +use std::io::ErrorKind; +use std::process::{Command, Stdio}; -pub fn check(_bad: &mut bool) { - let result = Command::new("x").arg("--version").output(); - let output = match result { - Ok(output) => output, - Err(_e) => todo!(), +pub fn check(bad: &mut bool) { + let result = Command::new("x") + .arg("--version") + .stdout(Stdio::piped()) + .spawn(); + let child = match result { + Ok(child) => child, + Err(e) => match e.kind() { + ErrorKind::NotFound => return (), + _ => return tidy_error!(bad, "{}", e), + }, }; + let output = child.wait_with_output().unwrap(); + if output.status.success() { let version = String::from_utf8_lossy(&output.stdout); - assert_eq!("0.1.0", version.trim_end()); + let version = Version::parse(version.trim_end()).unwrap(); + let expected = Version { + major: 0, + minor: 1, + patch: 0, + pre: Prerelease::new("").unwrap(), + build: BuildMetadata::EMPTY, + }; + if version < expected { + return tidy_error!(bad, "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`"); + } + } else { + return tidy_error!(bad, "{}", output.status); } - // FIXME: throw some kind of tidy error when the version of x isn't - // greater than or equal to the version we'd expect. - //tidy_error!(bad, "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`") } From a917308d9180b3203c1e65a394c28c7e7d92b9bb Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 5 Dec 2022 16:19:10 -0700 Subject: [PATCH 055/223] remove commented out old code --- src/bootstrap/bootstrap.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d7ba015982a4..f3998e98583e 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -934,7 +934,6 @@ def main(): if len(sys.argv) > 1 and sys.argv[1] == 'help': sys.argv = [sys.argv[0], '-h'] + sys.argv[2:] - # help_triggered = ('-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) help_triggered = len(sys.argv) == 1 or any(x in ["-h", "--help", "--version"] for x in sys.argv) try: bootstrap(help_triggered) From 7fe2f73ecdde41ec3bc0bd9bfdee5cd064536d53 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 5 Dec 2022 16:42:08 -0700 Subject: [PATCH 056/223] formatting --- src/tools/tidy/src/x_version.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index bbb2662bdcf6..c54414836ed7 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -3,14 +3,11 @@ use std::io::ErrorKind; use std::process::{Command, Stdio}; pub fn check(bad: &mut bool) { - let result = Command::new("x") - .arg("--version") - .stdout(Stdio::piped()) - .spawn(); + let result = Command::new("x").arg("--version").stdout(Stdio::piped()).spawn(); let child = match result { Ok(child) => child, Err(e) => match e.kind() { - ErrorKind::NotFound => return (), + ErrorKind::NotFound => return, _ => return tidy_error!(bad, "{}", e), }, }; @@ -28,7 +25,10 @@ pub fn check(bad: &mut bool) { build: BuildMetadata::EMPTY, }; if version < expected { - return tidy_error!(bad, "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`"); + return tidy_error!( + bad, + "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`" + ); } } else { return tidy_error!(bad, "{}", output.status); From 02173f6ab514cf98b73f053cbc0e7b9881c18783 Mon Sep 17 00:00:00 2001 From: J Haigh Date: Wed, 7 Dec 2022 13:28:57 -0700 Subject: [PATCH 057/223] Update error message Co-authored-by: Joshua Nelson --- src/tools/tidy/src/x_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index c54414836ed7..df9d780ea148 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -8,7 +8,7 @@ pub fn check(bad: &mut bool) { Ok(child) => child, Err(e) => match e.kind() { ErrorKind::NotFound => return, - _ => return tidy_error!(bad, "{}", e), + _ => return tidy_error!(bad, "failed to run `x`: {}", e), }, }; From 430ea8d440f5fc22dec7c4b6bda0536ae38baa00 Mon Sep 17 00:00:00 2001 From: J Haigh Date: Wed, 7 Dec 2022 13:29:10 -0700 Subject: [PATCH 058/223] Update error message Co-authored-by: Joshua Nelson --- src/tools/tidy/src/x_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index df9d780ea148..f0c7a308cfae 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -31,6 +31,6 @@ pub fn check(bad: &mut bool) { ); } } else { - return tidy_error!(bad, "{}", output.status); + return tidy_error!(bad, "failed to check version of `x`: {}", output.status); } } From f50ad6cd8ce48c8f159bee064ba9ae9dd28f6868 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Wed, 7 Dec 2022 14:00:40 -0700 Subject: [PATCH 059/223] rename wrapper-version argument for x to differentiate it from the bootstrap version --- src/tools/tidy/src/x_version.rs | 2 +- src/tools/x/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index f0c7a308cfae..dddf72f47471 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -3,7 +3,7 @@ use std::io::ErrorKind; use std::process::{Command, Stdio}; pub fn check(bad: &mut bool) { - let result = Command::new("x").arg("--version").stdout(Stdio::piped()).spawn(); + let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); let child = match result { Ok(child) => child, Err(e) => match e.kind() { diff --git a/src/tools/x/src/main.rs b/src/tools/x/src/main.rs index db5d03710d76..01f7187851e3 100644 --- a/src/tools/x/src/main.rs +++ b/src/tools/x/src/main.rs @@ -53,7 +53,7 @@ fn exec_or_status(command: &mut Command) -> io::Result { fn main() { match env::args().skip(1).next().as_deref() { - Some("--version") => { + Some("--wrapper-version") => { let version = env!("CARGO_PKG_VERSION"); println!("{}", version); return; From 04b9038610606313cf023e59fc6a0ef4d5d22340 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Thu, 29 Dec 2022 19:08:59 +1300 Subject: [PATCH 060/223] refactor: clean up `errors.rs` and `error_codes_check.rs` Move them into new `error_codes.rs` tidy check. --- compiler/rustc_error_codes/src/error_codes.rs | 1 - .../src/error_codes/E0729.md | 30 -- src/tools/tidy/src/error_codes.rs | 397 ++++++++++++++++++ src/tools/tidy/src/error_codes_check.rs | 305 -------------- src/tools/tidy/src/errors.rs | 77 ---- src/tools/tidy/src/lib.rs | 3 +- src/tools/tidy/src/main.rs | 4 +- 7 files changed, 400 insertions(+), 417 deletions(-) delete mode 100644 compiler/rustc_error_codes/src/error_codes/E0729.md create mode 100644 src/tools/tidy/src/error_codes.rs delete mode 100644 src/tools/tidy/src/error_codes_check.rs delete mode 100644 src/tools/tidy/src/errors.rs diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 3fba2cf57494..137325e6fabf 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -443,7 +443,6 @@ E0725: include_str!("./error_codes/E0725.md"), E0726: include_str!("./error_codes/E0726.md"), E0727: include_str!("./error_codes/E0727.md"), E0728: include_str!("./error_codes/E0728.md"), -E0729: include_str!("./error_codes/E0729.md"), E0730: include_str!("./error_codes/E0730.md"), E0731: include_str!("./error_codes/E0731.md"), E0732: include_str!("./error_codes/E0732.md"), diff --git a/compiler/rustc_error_codes/src/error_codes/E0729.md b/compiler/rustc_error_codes/src/error_codes/E0729.md deleted file mode 100644 index 74f89080b91a..000000000000 --- a/compiler/rustc_error_codes/src/error_codes/E0729.md +++ /dev/null @@ -1,30 +0,0 @@ -Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler -since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow -checker for NLL uncovered some bugs in the old borrow checker, which in some -cases allowed unsound code to compile, resulting in memory safety issues. - -### What do I do? - -Change your code so the warning does no longer trigger. For backwards -compatibility, this unsound code may still compile (with a warning) right now. -However, at some point in the future, the compiler will no longer accept this -code and will throw a hard error. - -### Shouldn't you fix the old borrow checker? - -The old borrow checker has known soundness issues that are basically impossible -to fix. The new NLL-based borrow checker is the fix. - -### Can I turn these warnings into errors by denying a lint? - -No. - -### When are these warnings going to turn into errors? - -No formal timeline for turning the warnings into errors has been set. See -[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more -information. - -### Why do I get this message with code that doesn't involve borrowing? - -There are some known bugs that trigger this message. diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs new file mode 100644 index 000000000000..f4aebbf22775 --- /dev/null +++ b/src/tools/tidy/src/error_codes.rs @@ -0,0 +1,397 @@ +//! Tidy check to ensure error codes are properly documented and tested. +//! +//! Overview of check: +//! +//! 1. We create a list of error codes used by the compiler. Error codes are extracted from `compiler/rustc_error_codes/src/error_codes.rs`. +//! +//! 2. We check that the error code has a long-form explanation in `compiler/rustc_error_codes/src/error_codes/`. +//! - The explanation is expected to contain a `doctest` that fails with the correct error code. (`EXEMPT_FROM_DOCTEST` *currently* bypasses this check) +//! - Note that other stylistic conventions for markdown files are checked in the `style.rs` tidy check. +//! +//! 3. We check that the error code has a UI test in `src/test/ui/error-codes/`. +//! - We ensure that there is both a `Exxxx.rs` file and a corresponding `Exxxx.stderr` file. +//! - We also ensure that the error code is used in the tests. +//! - *Currently*, it is possible to opt-out of this check with the `EXEMPTED_FROM_TEST` constant. +//! +//! 4. We check that the error code is actually emitted by the compiler. +//! - This is done by searching `compiler/` with a regex. +//! +//! This tidy check was merged and refactored from two others. See #PR_NUM for information about linting changes that occurred during this refactor. + +use std::{ffi::OsStr, fs, path::Path}; + +use regex::Regex; + +use crate::walk::{filter_dirs, walk, walk_many}; + +const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/error_codes.rs"; +const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/"; +const ERROR_TESTS_PATH: &str = "src/test/ui/error-codes/"; + +// Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested. +const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0729"]; + +// Error codes that don't yet have a UI test. This list will eventually be removed. +const IGNORE_UI_TEST_CHECK: &[&str] = &[ + "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", + "E0729", "E0789", +]; + +pub fn check(root_path: &Path, search_paths: &[&Path], bad: &mut bool) { + let mut errors = Vec::new(); + + // Stage 1: create list + let error_codes = extract_error_codes(root_path, &mut errors); + println!("Found {} error codes", error_codes.len()); + + // Stage 2: check list has docs + let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors); + + // Stage 3: check list has UI tests + check_error_codes_tests(root_path, &error_codes, &mut errors); + + // Stage 4: check list is emitted by compiler + check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted); + + // Print any errors. + for error in errors { + tidy_error!(bad, "{}", error); + } +} + +/// Stage 1: Parses a list of error codes from `error_codes.rs`. +fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec { + let file = fs::read_to_string(root_path.join(Path::new(ERROR_CODES_PATH))) + .unwrap_or_else(|e| panic!("failed to read `error_codes.rs`: {e}")); + + let mut error_codes = Vec::new(); + let mut reached_undocumented_codes = false; + + let mut undocumented_count = 0; + + for line in file.lines() { + let line = line.trim(); + + if !reached_undocumented_codes && line.starts_with('E') { + let split_line = line.split_once(':'); + + // Extract the error code from the line, emitting a fatal error if it is not in a correct format. + let err_code = if let Some(err_code) = split_line { + err_code.0.to_owned() + } else { + errors.push(format!( + "Expected a line with the format `Exxxx: include_str!(\"..\")`, but got \"{}\" \ + without a `:` delimiter", + line, + )); + continue; + }; + + // If this is a duplicate of another error code, emit a fatal error. + if error_codes.contains(&err_code) { + errors.push(format!("Found duplicate error code: `{}`", err_code)); + continue; + } + + // Ensure that the line references the correct markdown file. + let expected_filename = format!(" include_str!(\"./error_codes/{}.md\"),", err_code); + if expected_filename != split_line.unwrap().1 { + errors.push(format!( + "Error code `{}` expected to reference docs with `{}` but instead found `{}`", + err_code, + expected_filename, + split_line.unwrap().1, + )); + continue; + } + + error_codes.push(err_code); + } else if reached_undocumented_codes && line.starts_with('E') { + let err_code = match line.split_once(',') { + None => line, + Some((err_code, _)) => err_code, + } + .to_string(); + + undocumented_count += 1; + + if error_codes.contains(&err_code) { + errors.push(format!("Found duplicate error code: `{}`", err_code)); + } + + error_codes.push(err_code); + } else if line == ";" { + // Once we reach the undocumented error codes, adapt to different syntax. + reached_undocumented_codes = true; + } + } + + println!( + "WARNING: {} error codes are undocumented. This *will* become a hard error.", + undocumented_count + ); + + error_codes +} + +/// Stage 2: Checks that long-form error code explanations exist and have doctests. +fn check_error_codes_docs( + root_path: &Path, + error_codes: &[String], + errors: &mut Vec, +) -> Vec { + let docs_path = root_path.join(Path::new(ERROR_DOCS_PATH)); + + let mut emit_ignore_warning = 0; + let mut emit_no_longer_warning = 0; + let mut emit_no_code_warning = 0; + + let mut no_longer_emitted_codes = Vec::new(); + + walk(&docs_path, &mut |_| false, &mut |entry, contents| { + let path = entry.path(); + + // Error if the file isn't markdown. + if path.extension() != Some(OsStr::new("md")) { + errors.push(format!( + "Found unexpected non-markdown file in error code docs directory: {}", + path.display() + )); + return; + } + + // Make sure that the file is referenced in `error_codes.rs` + let filename = path.file_name().unwrap().to_str().unwrap().split_once('.'); + let err_code = filename.unwrap().0; // `unwrap` is ok because we know the filename is in the correct format. + + if error_codes.iter().all(|e| e != err_code) { + errors.push(format!( + "Found valid file `{}` in error code docs directory without corresponding \ + entry in `error_code.rs`", + path.display() + )); + return; + } + + // `has_test.0` checks whether the error code has any (potentially untested) code example. + // `has_test.1` checks whether the error code has a proper (definitely tested) doctest. + let has_test = check_explanation_has_doctest(&contents, &err_code); + if has_test.2 { + emit_ignore_warning += 1; + } + if has_test.3 { + no_longer_emitted_codes.push(err_code.to_owned()); + emit_no_longer_warning += 1; + } + if !has_test.0 { + emit_no_code_warning += 1; + } + + let test_ignored = IGNORE_DOCTEST_CHECK.contains(&err_code); + + // Check that the explanation has a doctest, and if it shouldn't, that it doesn't + if !has_test.1 && !test_ignored { + errors.push(format!( + "`{}` doesn't use its own error code in compile_fail example", + path.display(), + )); + } else if has_test.1 && test_ignored { + errors.push(format!( + "`{}` has a compile_fail doctest with its own error code, it shouldn't \ + be listed in `IGNORE_DOCTEST_CHECK`", + path.display(), + )); + } + }); + + if emit_ignore_warning > 0 { + println!( + "WARNING: {emit_ignore_warning} error codes use the ignore header. This should not be used, add the error codes to the \ + `IGNORE_DOCTEST_CHECK` constant instead. This *will* become a hard error." + ); + } + if emit_no_code_warning > 0 { + println!( + "WARNING: {emit_ignore_warning} error codes don't have a code example, all error codes are expected \ + to have one (even if untested). This *will* become a hard error." + ); + } + if emit_no_longer_warning > 0 { + println!( + "WARNING: {emit_no_longer_warning} error codes are no longer emitted and should be removed entirely. \ + This *will* become a hard error." + ); + } + + no_longer_emitted_codes +} + +/// This function returns a tuple indicating whether the provided explanation: +/// a) has a code example, tested or not. +/// b) has a valid doctest +fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bool, bool, bool) { + let mut found_code_example = false; + let mut found_proper_doctest = false; + + let mut emit_ignore_warning = false; + let mut emit_no_longer_warning = false; + + for line in explanation.lines() { + let line = line.trim(); + + if line.starts_with("```") { + found_code_example = true; + + // Check for the `rustdoc` doctest headers. + if line.contains("compile_fail") && line.contains(err_code) { + found_proper_doctest = true; + } + + if line.contains("ignore") { + emit_ignore_warning = true; + found_proper_doctest = true; + } + } else if line + .starts_with("#### Note: this error code is no longer emitted by the compiler") + { + emit_no_longer_warning = true; + found_code_example = true; + found_proper_doctest = true; + } + } + + (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) +} + +// Stage 3: Checks that each error code has a UI test in the correct directory +fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mut Vec) { + let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH)); + + // Some warning counters, this whole thing is clunky but'll be removed eventually. + let mut no_ui_test = 0; + let mut no_error_code_in_test = 0; + + for code in error_codes { + let test_path = tests_path.join(format!("{}.stderr", code)); + + if !test_path.exists() && !IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { + no_ui_test += 1; + continue; + } + if IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { + if test_path.exists() { + errors.push(format!( + "Error code `{code}` has a UI test, it shouldn't be listed in `EXEMPTED_FROM_TEST`!" + )); + } + continue; + } + + let file = match fs::read_to_string(test_path) { + Ok(file) => file, + Err(err) => { + println!( + "WARNING: Failed to read UI test file for `{code}` but the file exists. The test is assumed to work:\n{err}" + ); + continue; + } + }; + + let mut found_code = false; + + for line in file.lines() { + let s = line.trim(); + // Assuming the line starts with `error[E`, we can substring the error code out. + if s.starts_with("error[E") { + if &s[6..11] == code { + found_code = true; + break; + } + }; + } + + if !found_code { + no_error_code_in_test += 1; + } + } + + if no_error_code_in_test > 0 { + println!( + "WARNING: {no_error_code_in_test} error codes have a UI test file, but don't contain their own error code!" + ); + } + + if no_ui_test > 0 { + println!( + "WARNING: {no_ui_test} error codes need to have at least one UI test in the `src/test/ui/error-codes/` directory`! \ + This *will* become a hard error." + ); + } +} + +/// Stage 4: Search `compiler/` and ensure that every error code is actually used by the compiler and that no undocumented error codes exist. +fn check_error_codes_used( + search_paths: &[&Path], + error_codes: &[String], + errors: &mut Vec, + no_longer_emitted: &[String], +) { + // We want error codes which match the following cases: + // + // * foo(a, E0111, a) + // * foo(a, E0111) + // * foo(E0111, a) + // * #[error = "E0111"] + let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); + + let mut found_codes = Vec::new(); + + walk_many(search_paths, &mut filter_dirs, &mut |entry, contents| { + let path = entry.path(); + + // Return early if we aren't looking at a source file. + if path.extension() != Some(OsStr::new("rs")) { + return; + } + + for line in contents.lines() { + // We want to avoid parsing error codes in comments. + if line.trim_start().starts_with("//") { + continue; + } + + for cap in regex.captures_iter(line) { + if let Some(error_code) = cap.get(1) { + let error_code = error_code.as_str().to_owned(); + + if !error_codes.contains(&error_code) { + // This error code isn't properly defined, we must error. + errors.push(format!("Error code `{}` is used in the compiler but not defined and documented in `compiler/rustc_error_codes/src/error_codes.rs`.", error_code)); + continue; + } + + // This error code can now be marked as used. + found_codes.push(error_code); + } + } + } + }); + + let mut used_when_shouldnt = 0; + + for code in error_codes { + if !found_codes.contains(code) && !no_longer_emitted.contains(code) { + errors.push(format!("Error code `{code}` exists, but is not emitted by the compiler!")) + } + + if found_codes.contains(code) && no_longer_emitted.contains(code) { + used_when_shouldnt += 1; + } + } + + if used_when_shouldnt > 0 { + println!( + "WARNING: {used_when_shouldnt} error codes are used when they are marked as \"no longer emitted\"" + ); + } +} diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs deleted file mode 100644 index 3f060e437aca..000000000000 --- a/src/tools/tidy/src/error_codes_check.rs +++ /dev/null @@ -1,305 +0,0 @@ -//! Checks that all error codes have at least one test to prevent having error -//! codes that are silently not thrown by the compiler anymore. - -use crate::walk::{filter_dirs, walk}; -use std::collections::{HashMap, HashSet}; -use std::ffi::OsStr; -use std::fs::read_to_string; -use std::path::Path; - -use regex::Regex; - -// A few of those error codes can't be tested but all the others can and *should* be tested! -const EXEMPTED_FROM_TEST: &[&str] = &[ - "E0313", "E0461", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", - "E0789", -]; - -// Some error codes don't have any tests apparently... -const IGNORE_EXPLANATION_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0729"]; - -// If the file path contains any of these, we don't want to try to extract error codes from it. -// -// We need to declare each path in the windows version (with backslash). -const PATHS_TO_IGNORE_FOR_EXTRACTION: &[&str] = - &["src/test/", "src\\test\\", "src/doc/", "src\\doc\\", "src/tools/", "src\\tools\\"]; - -#[derive(Default, Debug)] -struct ErrorCodeStatus { - has_test: bool, - has_explanation: bool, - is_used: bool, -} - -fn check_error_code_explanation( - f: &str, - error_codes: &mut HashMap, - err_code: String, -) -> bool { - let mut invalid_compile_fail_format = false; - let mut found_error_code = false; - - for line in f.lines() { - let s = line.trim(); - if s.starts_with("```") { - if s.contains("compile_fail") && s.contains('E') { - if !found_error_code { - error_codes.get_mut(&err_code).map(|x| x.has_test = true); - found_error_code = true; - } - } else if s.contains("compile-fail") { - invalid_compile_fail_format = true; - } - } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { - if !found_error_code { - error_codes.get_mut(&err_code).map(|x| x.has_test = true); - found_error_code = true; - } - } - } - invalid_compile_fail_format -} - -fn check_if_error_code_is_test_in_explanation(f: &str, err_code: &str) -> bool { - let mut ignore_found = false; - - for line in f.lines() { - let s = line.trim(); - if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { - return true; - } - if s.starts_with("```") { - if s.contains("compile_fail") && s.contains(err_code) { - return true; - } else if s.contains("ignore") { - // It's very likely that we can't actually make it fail compilation... - ignore_found = true; - } - } - } - ignore_found -} - -fn extract_error_codes( - f: &str, - error_codes: &mut HashMap, - path: &Path, - errors: &mut Vec, -) { - let mut reached_no_explanation = false; - - for line in f.lines() { - let s = line.trim(); - if !reached_no_explanation && s.starts_with('E') && s.contains("include_str!(\"") { - let err_code = s - .split_once(':') - .expect( - format!( - "Expected a line with the format `E0xxx: include_str!(\"..\")`, but got {} \ - without a `:` delimiter", - s, - ) - .as_str(), - ) - .0 - .to_owned(); - error_codes.entry(err_code.clone()).or_default().has_explanation = true; - - // Now we extract the tests from the markdown file! - let md_file_name = match s.split_once("include_str!(\"") { - None => continue, - Some((_, md)) => match md.split_once("\")") { - None => continue, - Some((file_name, _)) => file_name, - }, - }; - - let Some(parent) = path.parent() else { - continue; - }; - - let path = parent - .join(md_file_name) - .canonicalize() - .expect("failed to canonicalize error explanation file path"); - - match read_to_string(&path) { - Ok(content) => { - let has_test = check_if_error_code_is_test_in_explanation(&content, &err_code); - if !has_test && !IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) { - errors.push(format!( - "`{}` doesn't use its own error code in compile_fail example", - path.display(), - )); - } else if has_test && IGNORE_EXPLANATION_CHECK.contains(&err_code.as_str()) { - errors.push(format!( - "`{}` has a compile_fail example with its own error code, it shouldn't \ - be listed in IGNORE_EXPLANATION_CHECK!", - path.display(), - )); - } - if check_error_code_explanation(&content, error_codes, err_code) { - errors.push(format!( - "`{}` uses invalid tag `compile-fail` instead of `compile_fail`", - path.display(), - )); - } - } - Err(e) => { - eprintln!("Couldn't read `{}`: {}", path.display(), e); - } - } - } else if reached_no_explanation && s.starts_with('E') { - let err_code = match s.split_once(',') { - None => s, - Some((err_code, _)) => err_code, - } - .to_string(); - if !error_codes.contains_key(&err_code) { - // this check should *never* fail! - error_codes.insert(err_code, ErrorCodeStatus::default()); - } - } else if s == ";" { - reached_no_explanation = true; - } - } -} - -fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap) { - for line in f.lines() { - let s = line.trim(); - if s.starts_with("error[E") || s.starts_with("warning[E") { - let err_code = match s.split_once(']') { - None => continue, - Some((err_code, _)) => match err_code.split_once('[') { - None => continue, - Some((_, err_code)) => err_code, - }, - }; - error_codes.entry(err_code.to_owned()).or_default().has_test = true; - } - } -} - -fn extract_error_codes_from_source( - f: &str, - error_codes: &mut HashMap, - regex: &Regex, -) { - for line in f.lines() { - if line.trim_start().starts_with("//") { - continue; - } - for cap in regex.captures_iter(line) { - if let Some(error_code) = cap.get(1) { - error_codes.entry(error_code.as_str().to_owned()).or_default().is_used = true; - } - } - } -} - -pub fn check(paths: &[&Path], bad: &mut bool) { - let mut errors = Vec::new(); - let mut found_explanations = 0; - let mut found_tests = 0; - let mut error_codes: HashMap = HashMap::new(); - let mut explanations: HashSet = HashSet::new(); - // We want error codes which match the following cases: - // - // * foo(a, E0111, a) - // * foo(a, E0111) - // * foo(E0111, a) - // * #[error = "E0111"] - let regex = Regex::new(r#"[(,"\s](E\d{4})[,)"]"#).unwrap(); - - for path in paths { - walk(path, &mut filter_dirs, &mut |entry, contents| { - let file_name = entry.file_name(); - let entry_path = entry.path(); - - if file_name == "error_codes.rs" { - extract_error_codes(contents, &mut error_codes, entry.path(), &mut errors); - found_explanations += 1; - } else if entry_path.extension() == Some(OsStr::new("stderr")) { - extract_error_codes_from_tests(contents, &mut error_codes); - found_tests += 1; - } else if entry_path.extension() == Some(OsStr::new("rs")) { - let path = entry.path().to_string_lossy(); - if PATHS_TO_IGNORE_FOR_EXTRACTION.iter().all(|c| !path.contains(c)) { - extract_error_codes_from_source(contents, &mut error_codes, ®ex); - } - } else if entry_path - .parent() - .and_then(|p| p.file_name()) - .map(|p| p == "error_codes") - .unwrap_or(false) - && entry_path.extension() == Some(OsStr::new("md")) - { - explanations.insert(file_name.to_str().unwrap().replace(".md", "")); - } - }); - } - if found_explanations == 0 { - tidy_error!(bad, "No error code explanation was tested!"); - } - if found_tests == 0 { - tidy_error!(bad, "No error code was found in compilation errors!"); - } - if explanations.is_empty() { - tidy_error!(bad, "No error code explanation was found!"); - } - if errors.is_empty() { - for (err_code, error_status) in &error_codes { - if !error_status.has_test && !EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { - errors.push(format!("Error code {err_code} needs to have at least one UI test!")); - } else if error_status.has_test && EXEMPTED_FROM_TEST.contains(&err_code.as_str()) { - errors.push(format!( - "Error code {} has a UI test, it shouldn't be listed into EXEMPTED_FROM_TEST!", - err_code - )); - } - if !error_status.is_used && !error_status.has_explanation { - errors.push(format!( - "Error code {} isn't used and doesn't have an error explanation, it should be \ - commented in error_codes.rs file", - err_code - )); - } - } - } - if errors.is_empty() { - // Checking if local constants need to be cleaned. - for err_code in EXEMPTED_FROM_TEST { - match error_codes.get(err_code.to_owned()) { - Some(status) => { - if status.has_test { - errors.push(format!( - "{} error code has a test and therefore should be \ - removed from the `EXEMPTED_FROM_TEST` constant", - err_code - )); - } - } - None => errors.push(format!( - "{} error code isn't used anymore and therefore should be removed \ - from `EXEMPTED_FROM_TEST` constant", - err_code - )), - } - } - } - if errors.is_empty() { - for explanation in explanations { - if !error_codes.contains_key(&explanation) { - errors.push(format!( - "{} error code explanation should be listed in `error_codes.rs`", - explanation - )); - } - } - } - errors.sort(); - for err in &errors { - tidy_error!(bad, "{err}"); - } -} diff --git a/src/tools/tidy/src/errors.rs b/src/tools/tidy/src/errors.rs deleted file mode 100644 index fe5fd72b91a4..000000000000 --- a/src/tools/tidy/src/errors.rs +++ /dev/null @@ -1,77 +0,0 @@ -//! Tidy check to verify the validity of long error diagnostic codes. -//! -//! This ensures that error codes are used at most once and also prints out some -//! statistics about the error codes. - -use crate::walk::{filter_dirs, walk}; -use std::collections::HashMap; -use std::path::Path; - -pub fn check(path: &Path, bad: &mut bool) { - let mut map: HashMap<_, Vec<_>> = HashMap::new(); - walk( - path, - &mut |path| filter_dirs(path) || path.ends_with("src/test"), - &mut |entry, contents| { - let file = entry.path(); - let filename = file.file_name().unwrap().to_string_lossy(); - if filename != "error_codes.rs" { - return; - } - - // In the `register_long_diagnostics!` macro, entries look like this: - // - // ``` - // EXXXX: r##" - // - // "##, - // ``` - // - // and these long messages often have error codes themselves inside - // them, but we don't want to report duplicates in these cases. This - // variable keeps track of whether we're currently inside one of these - // long diagnostic messages. - let mut inside_long_diag = false; - for (num, line) in contents.lines().enumerate() { - if inside_long_diag { - inside_long_diag = !line.contains("\"##"); - continue; - } - - let mut search = line; - while let Some(i) = search.find('E') { - search = &search[i + 1..]; - let code = if search.len() > 4 { search[..4].parse::() } else { continue }; - let code = match code { - Ok(n) => n, - Err(..) => continue, - }; - map.entry(code).or_default().push((file.to_owned(), num + 1, line.to_owned())); - break; - } - - inside_long_diag = line.contains("r##\""); - } - }, - ); - - let mut max = 0; - for (&code, entries) in map.iter() { - if code > max { - max = code; - } - if entries.len() == 1 { - continue; - } - - tidy_error!(bad, "duplicate error code: {}", code); - for &(ref file, line_num, ref line) in entries.iter() { - tidy_error!(bad, "{}:{}: {}", file.display(), line_num, line); - } - } - - if !*bad { - println!("* {} error codes", map.len()); - println!("* highest error code: E{:04}", max); - } -} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index ce7e7ac5cd4c..bf6e2cc250f3 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -56,8 +56,7 @@ pub mod bins; pub mod debug_artifacts; pub mod deps; pub mod edition; -pub mod error_codes_check; -pub mod errors; +pub mod error_codes; pub mod extdeps; pub mod features; pub mod mir_opt_tests; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 6714c63ee62a..8bb79bab1470 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -27,6 +27,7 @@ fn main() { let src_path = root_path.join("src"); let library_path = root_path.join("library"); let compiler_path = root_path.join("compiler"); + let librustdoc_path = src_path.join("librustdoc"); let args: Vec = env::args().skip(1).collect(); @@ -79,8 +80,7 @@ fn main() { check!(mir_opt_tests, &src_path, bless); // Checks that only make sense for the compiler. - check!(errors, &compiler_path); - check!(error_codes_check, &[&src_path, &compiler_path]); + check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path]); // Checks that only make sense for the std libs. check!(pal, &library_path); From 035d854947d5899388f77f6d00fc488caad86b5c Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Sun, 1 Jan 2023 18:48:14 +0100 Subject: [PATCH 061/223] reduce spans for `unsafe impl` errors --- .../src/coherence/unsafety.rs | 6 +++--- .../coherence-default-trait-impl.stderr | 4 ++-- .../dropck-eyepatch-implies-unsafe-impl.stderr | 18 ++++-------------- src/test/ui/error-codes/E0199.stderr | 2 +- src/test/ui/error-codes/E0200.stderr | 2 +- src/test/ui/traits/safety-trait-impl-cc.stderr | 8 ++------ src/test/ui/traits/safety-trait-impl.stderr | 4 ++-- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index a34815b45b3a..70cc15b2f8c5 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -21,7 +21,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { (Unsafety::Normal, None, Unsafety::Unsafe, hir::ImplPolarity::Positive) => { struct_span_err!( tcx.sess, - item.span, + tcx.def_span(def_id), E0199, "implementing the trait `{}` is not unsafe", trait_ref.print_only_trait_path() @@ -38,7 +38,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { (Unsafety::Unsafe, _, Unsafety::Normal, hir::ImplPolarity::Positive) => { struct_span_err!( tcx.sess, - item.span, + tcx.def_span(def_id), E0200, "the trait `{}` requires an `unsafe impl` declaration", trait_ref.print_only_trait_path() @@ -61,7 +61,7 @@ pub(super) fn check_item(tcx: TyCtxt<'_>, def_id: LocalDefId) { (Unsafety::Normal, Some(attr_name), Unsafety::Normal, hir::ImplPolarity::Positive) => { struct_span_err!( tcx.sess, - item.span, + tcx.def_span(def_id), E0569, "requires an `unsafe impl` declaration due to `#[{}]` attribute", attr_name diff --git a/src/test/ui/coherence/coherence-default-trait-impl.stderr b/src/test/ui/coherence/coherence-default-trait-impl.stderr index 632018782725..7be5b92a7def 100644 --- a/src/test/ui/coherence/coherence-default-trait-impl.stderr +++ b/src/test/ui/coherence/coherence-default-trait-impl.stderr @@ -2,7 +2,7 @@ error[E0199]: implementing the trait `MySafeTrait` is not unsafe --> $DIR/coherence-default-trait-impl.rs:8:1 | LL | unsafe impl MySafeTrait for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove `unsafe` from this trait implementation | @@ -14,7 +14,7 @@ error[E0200]: the trait `MyUnsafeTrait` requires an `unsafe impl` declaration --> $DIR/coherence-default-trait-impl.rs:13:1 | LL | impl MyUnsafeTrait for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `MyUnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation diff --git a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr index 82169ee01bed..5cec2bcb0387 100644 --- a/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr +++ b/src/test/ui/dropck/dropck-eyepatch-implies-unsafe-impl.stderr @@ -1,13 +1,8 @@ error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:21:1 | -LL | / impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { -LL | | -LL | | -LL | | // (unsafe to access self.1 due to #[may_dangle] on A) -LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } -LL | | } - | |_^ +LL | impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation @@ -18,13 +13,8 @@ LL | unsafe impl<#[may_dangle] A, B: fmt::Debug> Drop for Pt { error[E0569]: requires an `unsafe impl` declaration due to `#[may_dangle]` attribute --> $DIR/dropck-eyepatch-implies-unsafe-impl.rs:27:1 | -LL | / impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { -LL | | -LL | | -LL | | // (unsafe to access self.1 due to #[may_dangle] on 'a) -LL | | fn drop(&mut self) { println!("drop {} {:?}", self.0, self.2); } -LL | | } - | |_^ +LL | impl<#[may_dangle] 'a, 'b, B: fmt::Debug> Drop for Pr<'a, 'b, B> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `Drop` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation diff --git a/src/test/ui/error-codes/E0199.stderr b/src/test/ui/error-codes/E0199.stderr index 99d808c0d4b1..68c308b15cc0 100644 --- a/src/test/ui/error-codes/E0199.stderr +++ b/src/test/ui/error-codes/E0199.stderr @@ -2,7 +2,7 @@ error[E0199]: implementing the trait `Bar` is not unsafe --> $DIR/E0199.rs:6:1 | LL | unsafe impl Bar for Foo { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ | help: remove `unsafe` from this trait implementation | diff --git a/src/test/ui/error-codes/E0200.stderr b/src/test/ui/error-codes/E0200.stderr index 1fd86aecee17..c70a2d4f3d1f 100644 --- a/src/test/ui/error-codes/E0200.stderr +++ b/src/test/ui/error-codes/E0200.stderr @@ -2,7 +2,7 @@ error[E0200]: the trait `Bar` requires an `unsafe impl` declaration --> $DIR/E0200.rs:5:1 | LL | impl Bar for Foo { } - | ^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | = note: the trait `Bar` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation diff --git a/src/test/ui/traits/safety-trait-impl-cc.stderr b/src/test/ui/traits/safety-trait-impl-cc.stderr index 0b1fb30478ff..0ca565787f6b 100644 --- a/src/test/ui/traits/safety-trait-impl-cc.stderr +++ b/src/test/ui/traits/safety-trait-impl-cc.stderr @@ -1,12 +1,8 @@ error[E0200]: the trait `Foo` requires an `unsafe impl` declaration --> $DIR/safety-trait-impl-cc.rs:9:1 | -LL | / impl lib::Foo for Bar { -LL | | fn foo(&self) -> isize { -LL | | panic!(); -LL | | } -LL | | } - | |_^ +LL | impl lib::Foo for Bar { + | ^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `Foo` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation diff --git a/src/test/ui/traits/safety-trait-impl.stderr b/src/test/ui/traits/safety-trait-impl.stderr index 721e2b48b954..e78e0e3a6baa 100644 --- a/src/test/ui/traits/safety-trait-impl.stderr +++ b/src/test/ui/traits/safety-trait-impl.stderr @@ -2,7 +2,7 @@ error[E0200]: the trait `UnsafeTrait` requires an `unsafe impl` declaration --> $DIR/safety-trait-impl.rs:14:1 | LL | impl UnsafeTrait for u16 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the trait `UnsafeTrait` enforces invariants that the compiler can't check. Review the trait documentation and make sure this implementation upholds those invariants before adding the `unsafe` keyword help: add `unsafe` to this trait implementation @@ -14,7 +14,7 @@ error[E0199]: implementing the trait `SafeTrait` is not unsafe --> $DIR/safety-trait-impl.rs:16:1 | LL | unsafe impl SafeTrait for u32 { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: remove `unsafe` from this trait implementation | From ce28b4d408d260dab1bbcef4851506bb3089f4bc Mon Sep 17 00:00:00 2001 From: LegionMammal978 Date: Sun, 1 Jan 2023 13:47:11 -0500 Subject: [PATCH 062/223] Deallocate ThinBox even if the value unwinds on drop --- library/alloc/src/boxed/thin.rs | 47 ++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/library/alloc/src/boxed/thin.rs b/library/alloc/src/boxed/thin.rs index c477c44906c9..c1a82e452f6c 100644 --- a/library/alloc/src/boxed/thin.rs +++ b/library/alloc/src/boxed/thin.rs @@ -226,24 +226,45 @@ impl WithHeader { // - Assumes that either `value` can be dereferenced, or is the // `NonNull::dangling()` we use when both `T` and `H` are ZSTs. unsafe fn drop(&self, value: *mut T) { + struct DropGuard { + ptr: NonNull, + value_layout: Layout, + _marker: PhantomData, + } + + impl Drop for DropGuard { + fn drop(&mut self) { + unsafe { + // SAFETY: Layout must have been computable if we're in drop + let (layout, value_offset) = + WithHeader::::alloc_layout(self.value_layout).unwrap_unchecked(); + + // Note: Don't deallocate if the layout size is zero, because the pointer + // didn't come from the allocator. + if layout.size() != 0 { + alloc::dealloc(self.ptr.as_ptr().sub(value_offset), layout); + } else { + debug_assert!( + value_offset == 0 + && mem::size_of::() == 0 + && self.value_layout.size() == 0 + ); + } + } + } + } + unsafe { - let value_layout = Layout::for_value_raw(value); - // SAFETY: Layout must have been computable if we're in drop - let (layout, value_offset) = Self::alloc_layout(value_layout).unwrap_unchecked(); + // `_guard` will deallocate the memory when dropped, even if `drop_in_place` unwinds. + let _guard = DropGuard { + ptr: self.0, + value_layout: Layout::for_value_raw(value), + _marker: PhantomData::, + }; // We only drop the value because the Pointee trait requires that the metadata is copy // aka trivially droppable. ptr::drop_in_place::(value); - - // Note: Don't deallocate if the layout size is zero, because the pointer - // didn't come from the allocator. - if layout.size() != 0 { - alloc::dealloc(self.0.as_ptr().sub(value_offset), layout); - } else { - debug_assert!( - value_offset == 0 && mem::size_of::() == 0 && value_layout.size() == 0 - ); - } } } From 9618f646b314f934fe4ff92d6424255573c65a1c Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 09:11:36 +1300 Subject: [PATCH 063/223] docs: revert removal of `E0729` --- compiler/rustc_error_codes/src/error_codes.rs | 1 + .../src/error_codes/E0729.md | 32 +++++++++++++++++++ src/tools/tidy/src/error_codes.rs | 2 +- 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0729.md diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 137325e6fabf..3fba2cf57494 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -443,6 +443,7 @@ E0725: include_str!("./error_codes/E0725.md"), E0726: include_str!("./error_codes/E0726.md"), E0727: include_str!("./error_codes/E0727.md"), E0728: include_str!("./error_codes/E0728.md"), +E0729: include_str!("./error_codes/E0729.md"), E0730: include_str!("./error_codes/E0730.md"), E0731: include_str!("./error_codes/E0731.md"), E0732: include_str!("./error_codes/E0732.md"), diff --git a/compiler/rustc_error_codes/src/error_codes/E0729.md b/compiler/rustc_error_codes/src/error_codes/E0729.md new file mode 100644 index 000000000000..3891745b5008 --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0729.md @@ -0,0 +1,32 @@ +#### Note: this error code is no longer emitted by the compiler + +Support for Non-Lexical Lifetimes (NLL) has been included in the Rust compiler +since 1.31, and has been enabled on the 2015 edition since 1.36. The new borrow +checker for NLL uncovered some bugs in the old borrow checker, which in some +cases allowed unsound code to compile, resulting in memory safety issues. + +### What do I do? + +Change your code so the warning does no longer trigger. For backwards +compatibility, this unsound code may still compile (with a warning) right now. +However, at some point in the future, the compiler will no longer accept this +code and will throw a hard error. + +### Shouldn't you fix the old borrow checker? + +The old borrow checker has known soundness issues that are basically impossible +to fix. The new NLL-based borrow checker is the fix. + +### Can I turn these warnings into errors by denying a lint? + +No. + +### When are these warnings going to turn into errors? + +No formal timeline for turning the warnings into errors has been set. See +[GitHub issue 58781](https://github.com/rust-lang/rust/issues/58781) for more +information. + +### Why do I get this message with code that doesn't involve borrowing? + +There are some known bugs that trigger this message. diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index f4aebbf22775..b766f1667181 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -29,7 +29,7 @@ const ERROR_DOCS_PATH: &str = "compiler/rustc_error_codes/src/error_codes/"; const ERROR_TESTS_PATH: &str = "src/test/ui/error-codes/"; // Error codes that (for some reason) can't have a doctest in their explanation. Error codes are still expected to provide a code example, even if untested. -const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E0729"]; +const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"]; // Error codes that don't yet have a UI test. This list will eventually be removed. const IGNORE_UI_TEST_CHECK: &[&str] = &[ From 24671b7fd5daf16a39d6c9c62a457ace0b9c3ff6 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 09:15:36 +1300 Subject: [PATCH 064/223] use more paths in error codes --- src/tools/tidy/src/error_codes.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index b766f1667181..026f7d87418a 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -61,8 +61,9 @@ pub fn check(root_path: &Path, search_paths: &[&Path], bad: &mut bool) { /// Stage 1: Parses a list of error codes from `error_codes.rs`. fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec { - let file = fs::read_to_string(root_path.join(Path::new(ERROR_CODES_PATH))) - .unwrap_or_else(|e| panic!("failed to read `error_codes.rs`: {e}")); + let path = root_path.join(Path::new(ERROR_CODES_PATH)); + let file = + fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}")); let mut error_codes = Vec::new(); let mut reached_undocumented_codes = false; @@ -97,7 +98,8 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec file, Err(err) => { println!( - "WARNING: Failed to read UI test file for `{code}` but the file exists. The test is assumed to work:\n{err}" + "WARNING: Failed to read UI test file (`{test_path}`) for `{code}` but the file exists. The test is assumed to work:\n{err}" ); continue; } From 5e67ce6803c5d1d67ccfce653a80257aba41f43a Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Sun, 1 Jan 2023 13:20:32 -0700 Subject: [PATCH 065/223] handle error case where --wrapper-version argument doesn't exist --- src/tools/tidy/src/x_version.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index dddf72f47471..1505775c6cc6 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -4,15 +4,29 @@ use std::process::{Command, Stdio}; pub fn check(bad: &mut bool) { let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); - let child = match result { - Ok(child) => child, - Err(e) => match e.kind() { + // This runs the command inside a temporarily directory. + // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x. + let temp_result = Command::new("x").arg("--wrapper-version").current_dir(std::env::temp_dir()).stdout(Stdio::piped()).spawn(); + + let (child, temp_child) = match (result, temp_result) { + (Ok(child), Ok(temp_child)) => (child, temp_child), + // what would it mean if the temp cmd error'd? + (Ok(_child), Err(_e)) => todo!(), + (Err(e), _) => match e.kind() { ErrorKind::NotFound => return, _ => return tidy_error!(bad, "failed to run `x`: {}", e), }, }; let output = child.wait_with_output().unwrap(); + let temp_output = temp_child.wait_with_output().unwrap(); + + if output != temp_output { + return tidy_error!( + bad, + "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + ) + } if output.status.success() { let version = String::from_utf8_lossy(&output.stdout); From def1b7cb9ab99565cb3dc08d88035fd9cdb3c22a Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 09:20:41 +1300 Subject: [PATCH 066/223] fix CI error --- src/tools/tidy/src/error_codes.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 026f7d87418a..4498666da1e7 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -289,11 +289,12 @@ fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mu continue; } - let file = match fs::read_to_string(test_path) { + let file = match fs::read_to_string(&test_path) { Ok(file) => file, Err(err) => { println!( - "WARNING: Failed to read UI test file (`{test_path}`) for `{code}` but the file exists. The test is assumed to work:\n{err}" + "WARNING: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}", + test_path.display() ); continue; } From e94354e3632e76c6ccff91f40fa054f68e2e87f4 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Sun, 1 Jan 2023 13:41:47 -0700 Subject: [PATCH 067/223] fix formatting --- src/tools/tidy/src/x_version.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 1505775c6cc6..9cb762b9419f 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -6,7 +6,11 @@ pub fn check(bad: &mut bool) { let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); // This runs the command inside a temporarily directory. // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x. - let temp_result = Command::new("x").arg("--wrapper-version").current_dir(std::env::temp_dir()).stdout(Stdio::piped()).spawn(); + let temp_result = Command::new("x") + .arg("--wrapper-version") + .current_dir(std::env::temp_dir()) + .stdout(Stdio::piped()) + .spawn(); let (child, temp_child) = match (result, temp_result) { (Ok(child), Ok(temp_child)) => (child, temp_child), @@ -23,9 +27,9 @@ pub fn check(bad: &mut bool) { if output != temp_output { return tidy_error!( - bad, - "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" - ) + bad, + "Current version of x does not support the `--wrapper-version` argument\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + ); } if output.status.success() { From fafb18e0c45b60bacd08e2d8c8932401181dafbc Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 09:44:10 +1300 Subject: [PATCH 068/223] fixup warnings --- src/tools/tidy/src/error_codes.rs | 123 +++++++++++++----------------- src/tools/tidy/src/main.rs | 2 +- 2 files changed, 53 insertions(+), 72 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 4498666da1e7..ac87e4797c59 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -37,21 +37,29 @@ const IGNORE_UI_TEST_CHECK: &[&str] = &[ "E0729", "E0789", ]; -pub fn check(root_path: &Path, search_paths: &[&Path], bad: &mut bool) { +macro_rules! verbose_print { + ($verbose:expr, $($fmt:tt)*) => { + if $verbose { + println!("{}", format_args!($($fmt)*)); + } + }; +} + +pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut bool) { let mut errors = Vec::new(); // Stage 1: create list - let error_codes = extract_error_codes(root_path, &mut errors); + let error_codes = extract_error_codes(root_path, &mut errors, verbose); println!("Found {} error codes", error_codes.len()); // Stage 2: check list has docs - let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors); + let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose); // Stage 3: check list has UI tests - check_error_codes_tests(root_path, &error_codes, &mut errors); + check_error_codes_tests(root_path, &error_codes, &mut errors, verbose); // Stage 4: check list is emitted by compiler - check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted); + check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose); // Print any errors. for error in errors { @@ -60,7 +68,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], bad: &mut bool) { } /// Stage 1: Parses a list of error codes from `error_codes.rs`. -fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec { +fn extract_error_codes(root_path: &Path, errors: &mut Vec, verbose: bool) -> Vec { let path = root_path.join(Path::new(ERROR_CODES_PATH)); let file = fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}")); @@ -68,8 +76,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec) -> Vec) -> Vec) -> Vec, + verbose: bool, ) -> Vec { let docs_path = root_path.join(Path::new(ERROR_DOCS_PATH)); - let mut emit_ignore_warning = 0; - let mut emit_no_longer_warning = 0; - let mut emit_no_code_warning = 0; - let mut no_longer_emitted_codes = Vec::new(); walk(&docs_path, &mut |_| false, &mut |entry, contents| { @@ -179,14 +177,25 @@ fn check_error_codes_docs( // `has_test.1` checks whether the error code has a proper (definitely tested) doctest. let has_test = check_explanation_has_doctest(&contents, &err_code); if has_test.2 { - emit_ignore_warning += 1; + verbose_print!( + verbose, + "warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \ + `IGNORE_DOCTEST_CHECK` constant instead." + ); } if has_test.3 { no_longer_emitted_codes.push(err_code.to_owned()); - emit_no_longer_warning += 1; + verbose_print!( + verbose, + "warning: Error code `{err_code}` is no longer emitted and should be removed entirely." + ); } if !has_test.0 { - emit_no_code_warning += 1; + verbose_print!( + verbose, + "warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \ + (even if untested)." + ); } let test_ignored = IGNORE_DOCTEST_CHECK.contains(&err_code); @@ -206,25 +215,6 @@ fn check_error_codes_docs( } }); - if emit_ignore_warning > 0 { - println!( - "WARNING: {emit_ignore_warning} error codes use the ignore header. This should not be used, add the error codes to the \ - `IGNORE_DOCTEST_CHECK` constant instead. This *will* become a hard error." - ); - } - if emit_no_code_warning > 0 { - println!( - "WARNING: {emit_ignore_warning} error codes don't have a code example, all error codes are expected \ - to have one (even if untested). This *will* become a hard error." - ); - } - if emit_no_longer_warning > 0 { - println!( - "WARNING: {emit_no_longer_warning} error codes are no longer emitted and should be removed entirely. \ - This *will* become a hard error." - ); - } - no_longer_emitted_codes } @@ -266,18 +256,22 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo } // Stage 3: Checks that each error code has a UI test in the correct directory -fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mut Vec) { +fn check_error_codes_tests( + root_path: &Path, + error_codes: &[String], + errors: &mut Vec, + verbose: bool, +) { let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH)); - // Some warning counters, this whole thing is clunky but'll be removed eventually. - let mut no_ui_test = 0; - let mut no_error_code_in_test = 0; - for code in error_codes { let test_path = tests_path.join(format!("{}.stderr", code)); if !test_path.exists() && !IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { - no_ui_test += 1; + verbose_print!( + verbose, + "warning: Error code `{code}` needs to have at least one UI test in the `src/test/ui/error-codes/` directory`!" + ); continue; } if IGNORE_UI_TEST_CHECK.contains(&code.as_str()) { @@ -292,8 +286,9 @@ fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mu let file = match fs::read_to_string(&test_path) { Ok(file) => file, Err(err) => { - println!( - "WARNING: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}", + verbose_print!( + verbose, + "warning: Failed to read UI test file (`{}`) for `{code}` but the file exists. The test is assumed to work:\n{err}", test_path.display() ); continue; @@ -314,22 +309,12 @@ fn check_error_codes_tests(root_path: &Path, error_codes: &[String], errors: &mu } if !found_code { - no_error_code_in_test += 1; + verbose_print!( + verbose, + "warning: Error code {code}`` has a UI test file, but doesn't contain its own error code!" + ); } } - - if no_error_code_in_test > 0 { - println!( - "WARNING: {no_error_code_in_test} error codes have a UI test file, but don't contain their own error code!" - ); - } - - if no_ui_test > 0 { - println!( - "WARNING: {no_ui_test} error codes need to have at least one UI test in the `src/test/ui/error-codes/` directory`! \ - This *will* become a hard error." - ); - } } /// Stage 4: Search `compiler/` and ensure that every error code is actually used by the compiler and that no undocumented error codes exist. @@ -338,6 +323,7 @@ fn check_error_codes_used( error_codes: &[String], errors: &mut Vec, no_longer_emitted: &[String], + verbose: bool, ) { // We want error codes which match the following cases: // @@ -380,21 +366,16 @@ fn check_error_codes_used( } }); - let mut used_when_shouldnt = 0; - for code in error_codes { if !found_codes.contains(code) && !no_longer_emitted.contains(code) { errors.push(format!("Error code `{code}` exists, but is not emitted by the compiler!")) } if found_codes.contains(code) && no_longer_emitted.contains(code) { - used_when_shouldnt += 1; + verbose_print!( + verbose, + "warning: Error code `{code}` is used when it's marked as \"no longer emitted\"" + ); } } - - if used_when_shouldnt > 0 { - println!( - "WARNING: {used_when_shouldnt} error codes are used when they are marked as \"no longer emitted\"" - ); - } } diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 8bb79bab1470..a7b7cc9fa6c5 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -80,7 +80,7 @@ fn main() { check!(mir_opt_tests, &src_path, bless); // Checks that only make sense for the compiler. - check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path]); + check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose); // Checks that only make sense for the std libs. check!(pal, &library_path); From d7cac976dc3ce23fcd119e8194b1cb824e1800df Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Sun, 1 Jan 2023 14:34:40 -0700 Subject: [PATCH 069/223] combine error branches --- src/tools/tidy/src/x_version.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 9cb762b9419f..0a5055f61915 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -14,9 +14,7 @@ pub fn check(bad: &mut bool) { let (child, temp_child) = match (result, temp_result) { (Ok(child), Ok(temp_child)) => (child, temp_child), - // what would it mean if the temp cmd error'd? - (Ok(_child), Err(_e)) => todo!(), - (Err(e), _) => match e.kind() { + (Err(e), _) | (_, Err(e)) => match e.kind() { ErrorKind::NotFound => return, _ => return tidy_error!(bad, "failed to run `x`: {}", e), }, From e62258ebf45840721ff1aed0e3edb378205af0d3 Mon Sep 17 00:00:00 2001 From: J Haigh Date: Sun, 1 Jan 2023 14:36:11 -0700 Subject: [PATCH 070/223] fix typo Co-authored-by: Joshua Nelson --- src/tools/tidy/src/x_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 0a5055f61915..cf91749b9a4d 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -4,7 +4,7 @@ use std::process::{Command, Stdio}; pub fn check(bad: &mut bool) { let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); - // This runs the command inside a temporarily directory. + // This runs the command inside a temporary directory. // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x. let temp_result = Command::new("x") .arg("--wrapper-version") From 9aebb1e09950591413103545d5bc1a40ec46bd9e Mon Sep 17 00:00:00 2001 From: J Haigh Date: Sun, 1 Jan 2023 14:36:51 -0700 Subject: [PATCH 071/223] improve error message Co-authored-by: Joshua Nelson --- src/tools/tidy/src/x_version.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index cf91749b9a4d..868b3d925d3c 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -43,7 +43,7 @@ pub fn check(bad: &mut bool) { if version < expected { return tidy_error!( bad, - "Current version of x is {version} Consider updating to the newer version of x by running `cargo install --path src/tools/x`" + "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" ); } } else { From 74cdf933078d9a936ab5103b6c29148d61fe4b16 Mon Sep 17 00:00:00 2001 From: yukang Date: Thu, 15 Dec 2022 19:21:39 +0800 Subject: [PATCH 072/223] code refactor report_method_error --- .../rustc_hir_typeck/src/method/suggest.rs | 1805 ++++++++--------- 1 file changed, 897 insertions(+), 908 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 7053c180685c..d391e3182072 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -102,7 +102,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn report_method_error( &self, - mut span: Span, + span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, source: SelfSource<'tcx>, @@ -114,144 +114,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } - let report_candidates = |span: Span, - err: &mut Diagnostic, - sources: &mut Vec, - sugg_span: Option| { - sources.sort(); - sources.dedup(); - // Dynamic limit to avoid hiding just one candidate, which is silly. - let limit = if sources.len() == 5 { 5 } else { 4 }; - - for (idx, source) in sources.iter().take(limit).enumerate() { - match *source { - CandidateSource::Impl(impl_did) => { - // Provide the best span we can. Use the item, if local to crate, else - // the impl, if local to crate (item may be defaulted), else nothing. - let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { - let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; - self.associated_value(impl_trait_ref.def_id, item_name) - }) else { - continue; - }; - - let note_span = if item.def_id.is_local() { - Some(self.tcx.def_span(item.def_id)) - } else if impl_did.is_local() { - Some(self.tcx.def_span(impl_did)) - } else { - None - }; - - let impl_ty = self.tcx.at(span).type_of(impl_did); - - let insertion = match self.tcx.impl_trait_ref(impl_did) { - None => String::new(), - Some(trait_ref) => format!( - " of the trait `{}`", - self.tcx.def_path_str(trait_ref.def_id) - ), - }; - - let (note_str, idx) = if sources.len() > 1 { - ( - format!( - "candidate #{} is defined in an impl{} for the type `{}`", - idx + 1, - insertion, - impl_ty, - ), - Some(idx + 1), - ) - } else { - ( - format!( - "the candidate is defined in an impl{} for the type `{}`", - insertion, impl_ty, - ), - None, - ) - }; - if let Some(note_span) = note_span { - // We have a span pointing to the method. Show note with snippet. - err.span_note(note_span, ¬e_str); - } else { - err.note(¬e_str); - } - if let Some(sugg_span) = sugg_span - && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { - let path = self.tcx.def_path_str(trait_ref.def_id); - - let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, - ty::AssocKind::Fn => self - .tcx - .fn_sig(item.def_id) - .inputs() - .skip_binder() - .get(0) - .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr()) - .copied() - .unwrap_or(rcvr_ty), - }; - print_disambiguation_help( - item_name, - args, - err, - path, - ty, - item.kind, - item.def_id, - sugg_span, - idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ); - } - } - CandidateSource::Trait(trait_did) => { - let Some(item) = self.associated_value(trait_did, item_name) else { continue }; - let item_span = self.tcx.def_span(item.def_id); - let idx = if sources.len() > 1 { - let msg = &format!( - "candidate #{} is defined in the trait `{}`", - idx + 1, - self.tcx.def_path_str(trait_did) - ); - err.span_note(item_span, msg); - Some(idx + 1) - } else { - let msg = &format!( - "the candidate is defined in the trait `{}`", - self.tcx.def_path_str(trait_did) - ); - err.span_note(item_span, msg); - None - }; - if let Some(sugg_span) = sugg_span { - let path = self.tcx.def_path_str(trait_did); - print_disambiguation_help( - item_name, - args, - err, - path, - rcvr_ty, - item.kind, - item.def_id, - sugg_span, - idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ); - } - } - } - } - if sources.len() > limit { - err.note(&format!("and {} others", sources.len() - limit)); - } - }; - let sugg_span = if let SelfSource::MethodCall(expr) = source { // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing. self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span @@ -260,777 +122,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; match error { - MethodError::NoMatch(NoMatchData { - mut static_candidates, - unsatisfied_predicates, - out_of_scope_traits, - lev_candidate, - mode, - }) => { - let tcx = self.tcx; - - let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); - let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty)); - let is_method = mode == Mode::MethodCall; - let item_kind = if is_method { - "method" - } else if rcvr_ty.is_enum() { - "variant or associated item" - } else { - match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { - (Some(name), false) if name.is_lowercase() => "function or associated item", - (Some(_), false) => "associated item", - (Some(_), true) | (None, false) => "variant or associated item", - (None, true) => "variant", - } - }; - - if self.suggest_wrapping_range_with_parens( - tcx, rcvr_ty, source, span, item_name, &ty_str, - ) || self.suggest_constraining_numerical_ty( - tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str, - ) { - return None; - } - span = item_name.span; - - // Don't show generic arguments when the method can't be found in any implementation (#81576). - let mut ty_str_reported = ty_str.clone(); - if let ty::Adt(_, generics) = rcvr_ty.kind() { - if generics.len() > 0 { - let mut autoderef = self.autoderef(span, rcvr_ty); - let candidate_found = autoderef.any(|(ty, _)| { - if let ty::Adt(adt_def, _) = ty.kind() { - self.tcx - .inherent_impls(adt_def.did()) - .iter() - .filter_map(|def_id| self.associated_value(*def_id, item_name)) - .count() - >= 1 - } else { - false - } - }); - let has_deref = autoderef.step_count() > 0; - if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() { - if let Some((path_string, _)) = ty_str.split_once('<') { - ty_str_reported = path_string.to_string(); - } - } - } - } - - let mut err = struct_span_err!( - tcx.sess, + MethodError::NoMatch(mut no_match_data) => { + return self.report_no_match_method_error( span, - E0599, - "no {} named `{}` found for {} `{}` in the current scope", - item_kind, + rcvr_ty, item_name, - rcvr_ty.prefix_string(self.tcx), - ty_str_reported, + source, + args, + sugg_span, + &mut no_match_data, ); - if rcvr_ty.references_error() { - err.downgrade_to_delayed_bug(); - } - - if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source { - self.suggest_await_before_method( - &mut err, item_name, rcvr_ty, cal, span, - ); - } - if let Some(span) = - tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None)) - { - err.span_suggestion( - span.shrink_to_lo(), - "you are looking for the module in `std`, not the primitive type", - "std::", - Applicability::MachineApplicable, - ); - } - if let ty::RawPtr(_) = &rcvr_ty.kind() { - err.note( - "try using `<*const T>::as_ref()` to get a reference to the \ - type behind the pointer: https://doc.rust-lang.org/std/\ - primitive.pointer.html#method.as_ref", - ); - err.note( - "using `<*const T>::as_ref()` on a pointer which is unaligned or points \ - to invalid or uninitialized memory is undefined behavior", - ); - } - - let ty_span = match rcvr_ty.kind() { - ty::Param(param_type) => Some( - param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id()), - ), - ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())), - _ => None, - }; - if let Some(span) = ty_span { - err.span_label( - span, - format!( - "{item_kind} `{item_name}` not found for this {}", - rcvr_ty.prefix_string(self.tcx) - ), - ); - } - - if let SelfSource::MethodCall(rcvr_expr) = source { - self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { - let call_expr = self - .tcx - .hir() - .expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id)); - let probe = self.lookup_probe( - item_name, - output_ty, - call_expr, - ProbeScope::AllTraits, - ); - probe.is_ok() - }); - } - - let mut custom_span_label = false; - - if !static_candidates.is_empty() { - err.note( - "found the following associated functions; to be used as methods, \ - functions must have a `self` parameter", - ); - err.span_label(span, "this is an associated function, not a method"); - custom_span_label = true; - } - if static_candidates.len() == 1 { - self.suggest_associated_call_syntax( - &mut err, - &static_candidates, - rcvr_ty, - source, - item_name, - args, - sugg_span, - ); - - report_candidates(span, &mut err, &mut static_candidates, None); - } else if static_candidates.len() > 1 { - report_candidates(span, &mut err, &mut static_candidates, Some(sugg_span)); - } - - let mut bound_spans = vec![]; - let mut restrict_type_params = false; - let mut unsatisfied_bounds = false; - if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { - let msg = "consider using `len` instead"; - if let SelfSource::MethodCall(_expr) = source { - err.span_suggestion_short( - span, - msg, - "len", - Applicability::MachineApplicable, - ); - } else { - err.span_label(span, msg); - } - if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { - let iterator_trait = self.tcx.def_path_str(iterator_trait); - err.note(&format!("`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement")); - } - } else if !unsatisfied_predicates.is_empty() { - let mut type_params = FxHashMap::default(); - - // Pick out the list of unimplemented traits on the receiver. - // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute. - let mut unimplemented_traits = FxHashMap::default(); - let mut unimplemented_traits_only = true; - for (predicate, _parent_pred, cause) in &unsatisfied_predicates { - if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) = - (predicate.kind().skip_binder(), cause.as_ref()) - { - if p.trait_ref.self_ty() != rcvr_ty { - // This is necessary, not just to keep the errors clean, but also - // because our derived obligations can wind up with a trait ref that - // requires a different param_env to be correctly compared. - continue; - } - unimplemented_traits.entry(p.trait_ref.def_id).or_insert(( - predicate.kind().rebind(p.trait_ref), - Obligation { - cause: cause.clone(), - param_env: self.param_env, - predicate: *predicate, - recursion_depth: 0, - }, - )); - } - } - - // Make sure that, if any traits other than the found ones were involved, - // we don't don't report an unimplemented trait. - // We don't want to say that `iter::Cloned` is not an iterator, just - // because of some non-Clone item being iterated over. - for (predicate, _parent_pred, _cause) in &unsatisfied_predicates { - match predicate.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(p)) - if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {} - _ => { - unimplemented_traits_only = false; - break; - } - } - } - - let mut collect_type_param_suggestions = - |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| { - // We don't care about regions here, so it's fine to skip the binder here. - if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) = - (self_ty.kind(), parent_pred.kind().skip_binder()) - { - let hir = self.tcx.hir(); - let node = match p.trait_ref.self_ty().kind() { - ty::Param(_) => { - // Account for `fn` items like in `issue-35677.rs` to - // suggest restricting its type params. - let parent_body = - hir.body_owner(hir::BodyId { hir_id: self.body_id }); - Some(hir.get(parent_body)) - } - ty::Adt(def, _) => { - def.did().as_local().map(|def_id| hir.get_by_def_id(def_id)) - } - _ => None, - }; - if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { - if let Some(g) = kind.generics() { - let key = ( - g.tail_span_for_predicate_suggestion(), - g.add_where_or_trailing_comma(), - ); - type_params - .entry(key) - .or_insert_with(FxHashSet::default) - .insert(obligation.to_owned()); - } - } - } - }; - let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { - let msg = format!( - "doesn't satisfy `{}`", - if obligation.len() > 50 { quiet } else { obligation } - ); - match &self_ty.kind() { - // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => { - bound_spans.push((self.tcx.def_span(def.did()), msg)) - } - // Point at the trait object that couldn't satisfy the bound. - ty::Dynamic(preds, _, _) => { - for pred in preds.iter() { - match pred.skip_binder() { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push((self.tcx.def_span(tr.def_id), msg.clone())), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} - } - } - } - // Point at the closure that couldn't satisfy the bound. - ty::Closure(def_id, _) => bound_spans.push(( - tcx.def_span(*def_id), - format!("doesn't satisfy `{}`", quiet), - )), - _ => {} - } - }; - let mut format_pred = |pred: ty::Predicate<'tcx>| { - let bound_predicate = pred.kind(); - match bound_predicate.skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { - let pred = bound_predicate.rebind(pred); - // `::Item = String`. - let projection_ty = pred.skip_binder().projection_ty; - - let substs_with_infer_self = tcx.mk_substs( - iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into()) - .chain(projection_ty.substs.iter().skip(1)), - ); - - let quiet_projection_ty = - tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self); - - let term = pred.skip_binder().term; - - let obligation = format!("{} = {}", projection_ty, term); - let quiet = with_forced_trimmed_paths!(format!( - "{} = {}", - quiet_projection_ty, term - )); - - bound_span_label(projection_ty.self_ty(), &obligation, &quiet); - Some((obligation, projection_ty.self_ty())) - } - ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => { - let p = poly_trait_ref.trait_ref; - let self_ty = p.self_ty(); - let path = p.print_only_trait_path(); - let obligation = format!("{}: {}", self_ty, path); - let quiet = with_forced_trimmed_paths!(format!("_: {}", path)); - bound_span_label(self_ty, &obligation, &quiet); - Some((obligation, self_ty)) - } - _ => None, - } - }; - - // Find all the requirements that come from a local `impl` block. - let mut skip_list: FxHashSet<_> = Default::default(); - let mut spanned_predicates: FxHashMap = Default::default(); - for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates - .iter() - .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) - .filter_map(|(p, parent, c)| match c.code() { - ObligationCauseCode::ImplDerivedObligation(data) => { - Some((&data.derived, p, parent, data.impl_def_id, data)) - } - _ => None, - }) - { - let parent_trait_ref = data.parent_trait_pred; - let path = parent_trait_ref.print_modifiers_and_trait_path(); - let tr_self_ty = parent_trait_ref.skip_binder().self_ty(); - let unsatisfied_msg = "unsatisfied trait bound introduced here"; - let derive_msg = - "unsatisfied trait bound introduced in this `derive` macro"; - match self.tcx.hir().get_if_local(impl_def_id) { - // Unmet obligation comes from a `derive` macro, point at it once to - // avoid multiple span labels pointing at the same place. - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), - .. - })) if matches!( - self_ty.span.ctxt().outer_expn_data().kind, - ExpnKind::Macro(MacroKind::Derive, _) - ) || matches!( - of_trait.as_ref().map(|t| t - .path - .span - .ctxt() - .outer_expn_data() - .kind), - Some(ExpnKind::Macro(MacroKind::Derive, _)) - ) => - { - let span = self_ty.span.ctxt().outer_expn_data().call_site; - let mut spans: MultiSpan = span.into(); - spans.push_span_label(span, derive_msg); - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); - } - - // Unmet obligation coming from an `impl`. - Some(Node::Item(hir::Item { - kind: - hir::ItemKind::Impl(hir::Impl { - of_trait, self_ty, generics, .. - }), - span: item_span, - .. - })) => { - let sized_pred = - unsatisfied_predicates.iter().any(|(pred, _, _)| { - match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { - Some(pred.def_id()) - == self.tcx.lang_items().sized_trait() - && pred.polarity == ty::ImplPolarity::Positive - } - _ => false, - } - }); - for param in generics.params { - if param.span == cause.span && sized_pred { - let (sp, sugg) = match param.colon_span { - Some(sp) => (sp.shrink_to_hi(), " ?Sized +"), - None => (param.span.shrink_to_hi(), ": ?Sized"), - }; - err.span_suggestion_verbose( - sp, - "consider relaxing the type parameter's implicit \ - `Sized` bound", - sugg, - Applicability::MachineApplicable, - ); - } - } - if let Some(pred) = parent_p { - // Done to add the "doesn't satisfy" `span_label`. - let _ = format_pred(*pred); - } - skip_list.insert(p); - let mut spans = if cause.span != *item_span { - let mut spans: MultiSpan = cause.span.into(); - spans.push_span_label(cause.span, unsatisfied_msg); - spans - } else { - let mut spans = Vec::with_capacity(2); - if let Some(trait_ref) = of_trait { - spans.push(trait_ref.path.span); - } - spans.push(self_ty.span); - spans.into() - }; - if let Some(trait_ref) = of_trait { - spans.push_span_label(trait_ref.path.span, ""); - } - spans.push_span_label(self_ty.span, ""); - - let entry = spanned_predicates.entry(spans); - entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); - } - Some(Node::Item(hir::Item { - kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..), - span: item_span, - .. - })) => { - tcx.sess.delay_span_bug( - *item_span, - "auto trait is invoked with no method error, but no error reported?", - ); - } - Some(_) => unreachable!(), - None => (), - } - } - let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); - spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span()); - for (span, (_path, _self_ty, preds)) in spanned_predicates { - let mut preds: Vec<_> = preds - .into_iter() - .filter_map(|pred| format_pred(*pred)) - .map(|(p, _)| format!("`{}`", p)) - .collect(); - preds.sort(); - preds.dedup(); - let msg = if let [pred] = &preds[..] { - format!("trait bound {} was not satisfied", pred) - } else { - format!( - "the following trait bounds were not satisfied:\n{}", - preds.join("\n"), - ) - }; - err.span_note(span, &msg); - unsatisfied_bounds = true; - } - - // The requirements that didn't have an `impl` span to show. - let mut bound_list = unsatisfied_predicates - .iter() - .filter_map(|(pred, parent_pred, _cause)| { - format_pred(*pred).map(|(p, self_ty)| { - collect_type_param_suggestions(self_ty, *pred, &p); - ( - match parent_pred { - None => format!("`{}`", &p), - Some(parent_pred) => match format_pred(*parent_pred) { - None => format!("`{}`", &p), - Some((parent_p, _)) => { - collect_type_param_suggestions( - self_ty, - *parent_pred, - &p, - ); - format!( - "`{}`\nwhich is required by `{}`", - p, parent_p - ) - } - }, - }, - *pred, - ) - }) - }) - .filter(|(_, pred)| !skip_list.contains(&pred)) - .map(|(t, _)| t) - .enumerate() - .collect::>(); - - for ((span, add_where_or_comma), obligations) in type_params.into_iter() { - restrict_type_params = true; - // #74886: Sort here so that the output is always the same. - let mut obligations = obligations.into_iter().collect::>(); - obligations.sort(); - err.span_suggestion_verbose( - span, - &format!( - "consider restricting the type parameter{s} to satisfy the \ - trait bound{s}", - s = pluralize!(obligations.len()) - ), - format!("{} {}", add_where_or_comma, obligations.join(", ")), - Applicability::MaybeIncorrect, - ); - } - - bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. - bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677 - bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order. - - if !bound_list.is_empty() || !skip_list.is_empty() { - let bound_list = bound_list - .into_iter() - .map(|(_, path)| path) - .collect::>() - .join("\n"); - let actual_prefix = rcvr_ty.prefix_string(self.tcx); - info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); - let (primary_message, label) = - if unimplemented_traits.len() == 1 && unimplemented_traits_only { - unimplemented_traits - .into_iter() - .next() - .map(|(_, (trait_ref, obligation))| { - if trait_ref.self_ty().references_error() - || rcvr_ty.references_error() - { - // Avoid crashing. - return (None, None); - } - let OnUnimplementedNote { message, label, .. } = self - .err_ctxt() - .on_unimplemented_note(trait_ref, &obligation); - (message, label) - }) - .unwrap() - } else { - (None, None) - }; - let primary_message = primary_message.unwrap_or_else(|| format!( - "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \ - but its trait bounds were not satisfied" - )); - err.set_primary_message(&primary_message); - if let Some(label) = label { - custom_span_label = true; - err.span_label(span, label); - } - if !bound_list.is_empty() { - err.note(&format!( - "the following trait bounds were not satisfied:\n{bound_list}" - )); - } - self.suggest_derive(&mut err, &unsatisfied_predicates); - - unsatisfied_bounds = true; - } - } - - let label_span_not_found = |err: &mut Diagnostic| { - if unsatisfied_predicates.is_empty() { - err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); - let is_string_or_ref_str = match rcvr_ty.kind() { - ty::Ref(_, ty, _) => { - ty.is_str() - || matches!( - ty.kind(), - ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string() - ) - } - ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(), - _ => false, - }; - if is_string_or_ref_str && item_name.name == sym::iter { - err.span_suggestion_verbose( - item_name.span, - "because of the in-memory representation of `&str`, to obtain \ - an `Iterator` over each of its codepoint use method `chars`", - "chars", - Applicability::MachineApplicable, - ); - } - if let ty::Adt(adt, _) = rcvr_ty.kind() { - let mut inherent_impls_candidate = self - .tcx - .inherent_impls(adt.did()) - .iter() - .copied() - .filter(|def_id| { - if let Some(assoc) = self.associated_value(*def_id, item_name) { - // Check for both mode is the same so we avoid suggesting - // incorrect associated item. - match (mode, assoc.fn_has_self_parameter, source) { - (Mode::MethodCall, true, SelfSource::MethodCall(_)) => { - // We check that the suggest type is actually - // different from the received one - // So we avoid suggestion method with Box - // for instance - self.tcx.at(span).type_of(*def_id) != rcvr_ty - && self.tcx.at(span).type_of(*def_id) != rcvr_ty - } - (Mode::Path, false, _) => true, - _ => false, - } - } else { - false - } - }) - .collect::>(); - if !inherent_impls_candidate.is_empty() { - inherent_impls_candidate.sort(); - inherent_impls_candidate.dedup(); - - // number of type to shows at most. - let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 }; - let type_candidates = inherent_impls_candidate - .iter() - .take(limit) - .map(|impl_item| { - format!("- `{}`", self.tcx.at(span).type_of(*impl_item)) - }) - .collect::>() - .join("\n"); - let additional_types = if inherent_impls_candidate.len() > limit { - format!( - "\nand {} more types", - inherent_impls_candidate.len() - limit - ) - } else { - "".to_string() - }; - err.note(&format!( - "the {item_kind} was found for\n{}{}", - type_candidates, additional_types - )); - } - } - } else { - let ty_str = if ty_str.len() > 50 { - String::new() - } else { - format!("on `{ty_str}` ") - }; - err.span_label(span, format!( - "{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds" - )); - } - }; - - // If the method name is the name of a field with a function or closure type, - // give a helping note that it has to be called as `(x.f)(...)`. - if let SelfSource::MethodCall(expr) = source { - if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err) - && lev_candidate.is_none() - && !custom_span_label - { - label_span_not_found(&mut err); - } - } else if !custom_span_label { - label_span_not_found(&mut err); - } - - // Don't suggest (for example) `expr.field.clone()` if `expr.clone()` - // can't be called due to `typeof(expr): Clone` not holding. - if unsatisfied_predicates.is_empty() { - self.suggest_calling_method_on_field( - &mut err, source, span, rcvr_ty, item_name, - ); - } - - self.check_for_inner_self(&mut err, source, rcvr_ty, item_name); - - bound_spans.sort(); - bound_spans.dedup(); - for (span, msg) in bound_spans.into_iter() { - err.span_label(span, &msg); - } - - if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { - } else { - self.suggest_traits_to_import( - &mut err, - span, - rcvr_ty, - item_name, - args.map(|(_, args)| args.len() + 1), - source, - out_of_scope_traits, - &unsatisfied_predicates, - &static_candidates, - unsatisfied_bounds, - ); - } - - // Don't emit a suggestion if we found an actual method - // that had unsatisfied trait bounds - if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() { - let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT"); - if let Some(suggestion) = lev_distance::find_best_match_for_name( - &adt_def.variants().iter().map(|s| s.name).collect::>(), - item_name.name, - None, - ) { - err.span_suggestion( - span, - "there is a variant with a similar name", - suggestion, - Applicability::MaybeIncorrect, - ); - } - } - - if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() { - let msg = "remove this method call"; - let mut fallback_span = true; - if let SelfSource::MethodCall(expr) = source { - let call_expr = - self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); - if let Some(span) = call_expr.span.trim_start(expr.span) { - err.span_suggestion(span, msg, "", Applicability::MachineApplicable); - fallback_span = false; - } - } - if fallback_span { - err.span_label(span, msg); - } - } else if let Some(lev_candidate) = lev_candidate { - // Don't emit a suggestion if we found an actual method - // that had unsatisfied trait bounds - if unsatisfied_predicates.is_empty() { - let def_kind = lev_candidate.kind.as_def_kind(); - // Methods are defined within the context of a struct and their first parameter is always self, - // which represents the instance of the struct the method is being called on - // Associated functions don’t take self as a parameter and - // they are not methods because they don’t have an instance of the struct to work with. - if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter { - err.span_suggestion( - span, - "there is a method with a similar name", - lev_candidate.name, - Applicability::MaybeIncorrect, - ); - } else { - err.span_suggestion( - span, - &format!( - "there is {} {} with a similar name", - def_kind.article(), - def_kind.descr(lev_candidate.def_id), - ), - lev_candidate.name, - Applicability::MaybeIncorrect, - ); - } - } - } - - self.check_for_deref_method(&mut err, source, rcvr_ty, item_name); - - return Some(err); } MethodError::Ambiguity(mut sources) => { @@ -1042,7 +143,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(item_name.span, format!("multiple `{}` found", item_name)); - report_candidates(span, &mut err, &mut sources, Some(sugg_span)); + self.note_candidates_on_method_error( + rcvr_ty, + item_name, + args, + span, + &mut err, + &mut sources, + Some(sugg_span), + ); err.emit(); } @@ -1099,6 +208,886 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } + pub fn report_no_match_method_error( + &self, + mut span: Span, + rcvr_ty: Ty<'tcx>, + item_name: Ident, + source: SelfSource<'tcx>, + args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, + sugg_span: Span, + no_match_data: &mut NoMatchData<'tcx>, + ) -> Option> { + let mode = no_match_data.mode; + let tcx = self.tcx; + let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); + let ty_str = self.ty_to_string(rcvr_ty); + let is_method = mode == Mode::MethodCall; + let unsatisfied_predicates = &no_match_data.unsatisfied_predicates; + let lev_candidate = no_match_data.lev_candidate; + let item_kind = if is_method { + "method" + } else if rcvr_ty.is_enum() { + "variant or associated item" + } else { + match (item_name.as_str().chars().next(), rcvr_ty.is_fresh_ty()) { + (Some(name), false) if name.is_lowercase() => "function or associated item", + (Some(_), false) => "associated item", + (Some(_), true) | (None, false) => "variant or associated item", + (None, true) => "variant", + } + }; + + if self.suggest_wrapping_range_with_parens(tcx, rcvr_ty, source, span, item_name, &ty_str) + || self.suggest_constraining_numerical_ty( + tcx, rcvr_ty, source, span, item_kind, item_name, &ty_str, + ) + { + return None; + } + span = item_name.span; + + // Don't show generic arguments when the method can't be found in any implementation (#81576). + let mut ty_str_reported = ty_str.clone(); + if let ty::Adt(_, generics) = rcvr_ty.kind() { + if generics.len() > 0 { + let mut autoderef = self.autoderef(span, rcvr_ty); + let candidate_found = autoderef.any(|(ty, _)| { + if let ty::Adt(adt_def, _) = ty.kind() { + self.tcx + .inherent_impls(adt_def.did()) + .iter() + .filter_map(|def_id| self.associated_value(*def_id, item_name)) + .count() + >= 1 + } else { + false + } + }); + let has_deref = autoderef.step_count() > 0; + if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() { + if let Some((path_string, _)) = ty_str.split_once('<') { + ty_str_reported = path_string.to_string(); + } + } + } + } + + let mut err = struct_span_err!( + tcx.sess, + span, + E0599, + "no {} named `{}` found for {} `{}` in the current scope", + item_kind, + item_name, + rcvr_ty.prefix_string(self.tcx), + ty_str_reported, + ); + if rcvr_ty.references_error() { + err.downgrade_to_delayed_bug(); + } + + if let Mode::MethodCall = mode && let SelfSource::MethodCall(cal) = source { + self.suggest_await_before_method( + &mut err, item_name, rcvr_ty, cal, span, + ); + } + if let Some(span) = + tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None)) + { + err.span_suggestion( + span.shrink_to_lo(), + "you are looking for the module in `std`, not the primitive type", + "std::", + Applicability::MachineApplicable, + ); + } + if let ty::RawPtr(_) = &rcvr_ty.kind() { + err.note( + "try using `<*const T>::as_ref()` to get a reference to the \ + type behind the pointer: https://doc.rust-lang.org/std/\ + primitive.pointer.html#method.as_ref", + ); + err.note( + "using `<*const T>::as_ref()` on a pointer which is unaligned or points \ + to invalid or uninitialized memory is undefined behavior", + ); + } + + let ty_span = match rcvr_ty.kind() { + ty::Param(param_type) => { + Some(param_type.span_from_generics(self.tcx, self.body_id.owner.to_def_id())) + } + ty::Adt(def, _) if def.did().is_local() => Some(tcx.def_span(def.did())), + _ => None, + }; + if let Some(span) = ty_span { + err.span_label( + span, + format!( + "{item_kind} `{item_name}` not found for this {}", + rcvr_ty.prefix_string(self.tcx) + ), + ); + } + + if let SelfSource::MethodCall(rcvr_expr) = source { + self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { + let call_expr = + self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id)); + let probe = + self.lookup_probe(item_name, output_ty, call_expr, ProbeScope::AllTraits); + probe.is_ok() + }); + } + + let mut custom_span_label = false; + + let static_candidates = &mut no_match_data.static_candidates; + if !static_candidates.is_empty() { + err.note( + "found the following associated functions; to be used as methods, \ + functions must have a `self` parameter", + ); + err.span_label(span, "this is an associated function, not a method"); + custom_span_label = true; + } + if static_candidates.len() == 1 { + self.suggest_associated_call_syntax( + &mut err, + &static_candidates, + rcvr_ty, + source, + item_name, + args, + sugg_span, + ); + + self.note_candidates_on_method_error( + rcvr_ty, + item_name, + args, + span, + &mut err, + static_candidates, + None, + ); + } else if static_candidates.len() > 1 { + self.note_candidates_on_method_error( + rcvr_ty, + item_name, + args, + span, + &mut err, + static_candidates, + Some(sugg_span), + ); + } + + let mut bound_spans = vec![]; + let mut restrict_type_params = false; + let mut unsatisfied_bounds = false; + if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) { + let msg = "consider using `len` instead"; + if let SelfSource::MethodCall(_expr) = source { + err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable); + } else { + err.span_label(span, msg); + } + if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) { + let iterator_trait = self.tcx.def_path_str(iterator_trait); + err.note(&format!( + "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement" + )); + } + } else if !unsatisfied_predicates.is_empty() { + let mut type_params = FxHashMap::default(); + + // Pick out the list of unimplemented traits on the receiver. + // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute. + let mut unimplemented_traits = FxHashMap::default(); + let mut unimplemented_traits_only = true; + for (predicate, _parent_pred, cause) in unsatisfied_predicates { + if let (ty::PredicateKind::Clause(ty::Clause::Trait(p)), Some(cause)) = + (predicate.kind().skip_binder(), cause.as_ref()) + { + if p.trait_ref.self_ty() != rcvr_ty { + // This is necessary, not just to keep the errors clean, but also + // because our derived obligations can wind up with a trait ref that + // requires a different param_env to be correctly compared. + continue; + } + unimplemented_traits.entry(p.trait_ref.def_id).or_insert(( + predicate.kind().rebind(p.trait_ref), + Obligation { + cause: cause.clone(), + param_env: self.param_env, + predicate: *predicate, + recursion_depth: 0, + }, + )); + } + } + + // Make sure that, if any traits other than the found ones were involved, + // we don't don't report an unimplemented trait. + // We don't want to say that `iter::Cloned` is not an iterator, just + // because of some non-Clone item being iterated over. + for (predicate, _parent_pred, _cause) in unsatisfied_predicates { + match predicate.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(p)) + if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {} + _ => { + unimplemented_traits_only = false; + break; + } + } + } + + let mut collect_type_param_suggestions = + |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| { + // We don't care about regions here, so it's fine to skip the binder here. + if let (ty::Param(_), ty::PredicateKind::Clause(ty::Clause::Trait(p))) = + (self_ty.kind(), parent_pred.kind().skip_binder()) + { + let hir = self.tcx.hir(); + let node = match p.trait_ref.self_ty().kind() { + ty::Param(_) => { + // Account for `fn` items like in `issue-35677.rs` to + // suggest restricting its type params. + let parent_body = + hir.body_owner(hir::BodyId { hir_id: self.body_id }); + Some(hir.get(parent_body)) + } + ty::Adt(def, _) => { + def.did().as_local().map(|def_id| hir.get_by_def_id(def_id)) + } + _ => None, + }; + if let Some(hir::Node::Item(hir::Item { kind, .. })) = node { + if let Some(g) = kind.generics() { + let key = ( + g.tail_span_for_predicate_suggestion(), + g.add_where_or_trailing_comma(), + ); + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); + } + } + } + }; + let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { + let msg = format!( + "doesn't satisfy `{}`", + if obligation.len() > 50 { quiet } else { obligation } + ); + match &self_ty.kind() { + // Point at the type that couldn't satisfy the bound. + ty::Adt(def, _) => bound_spans.push((self.tcx.def_span(def.did()), msg)), + // Point at the trait object that couldn't satisfy the bound. + ty::Dynamic(preds, _, _) => { + for pred in preds.iter() { + match pred.skip_binder() { + ty::ExistentialPredicate::Trait(tr) => { + bound_spans.push((self.tcx.def_span(tr.def_id), msg.clone())) + } + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + } + // Point at the closure that couldn't satisfy the bound. + ty::Closure(def_id, _) => bound_spans + .push((tcx.def_span(*def_id), format!("doesn't satisfy `{}`", quiet))), + _ => {} + } + }; + let mut format_pred = |pred: ty::Predicate<'tcx>| { + let bound_predicate = pred.kind(); + match bound_predicate.skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Projection(pred)) => { + let pred = bound_predicate.rebind(pred); + // `::Item = String`. + let projection_ty = pred.skip_binder().projection_ty; + + let substs_with_infer_self = tcx.mk_substs( + iter::once(tcx.mk_ty_var(ty::TyVid::from_u32(0)).into()) + .chain(projection_ty.substs.iter().skip(1)), + ); + + let quiet_projection_ty = + tcx.mk_alias_ty(projection_ty.def_id, substs_with_infer_self); + + let term = pred.skip_binder().term; + + let obligation = format!("{} = {}", projection_ty, term); + let quiet = format!("{} = {}", quiet_projection_ty, term); + + bound_span_label(projection_ty.self_ty(), &obligation, &quiet); + Some((obligation, projection_ty.self_ty())) + } + ty::PredicateKind::Clause(ty::Clause::Trait(poly_trait_ref)) => { + let p = poly_trait_ref.trait_ref; + let self_ty = p.self_ty(); + let path = p.print_only_trait_path(); + let obligation = format!("{}: {}", self_ty, path); + let quiet = format!("_: {}", path); + bound_span_label(self_ty, &obligation, &quiet); + Some((obligation, self_ty)) + } + _ => None, + } + }; + + // Find all the requirements that come from a local `impl` block. + let mut skip_list: FxHashSet<_> = Default::default(); + let mut spanned_predicates: FxHashMap = Default::default(); + for (data, p, parent_p, impl_def_id, cause) in unsatisfied_predicates + .iter() + .filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c))) + .filter_map(|(p, parent, c)| match c.code() { + ObligationCauseCode::ImplDerivedObligation(data) => { + Some((&data.derived, p, parent, data.impl_def_id, data)) + } + _ => None, + }) + { + let parent_trait_ref = data.parent_trait_pred; + let path = parent_trait_ref.print_modifiers_and_trait_path(); + let tr_self_ty = parent_trait_ref.skip_binder().self_ty(); + let unsatisfied_msg = "unsatisfied trait bound introduced here"; + let derive_msg = "unsatisfied trait bound introduced in this `derive` macro"; + match self.tcx.hir().get_if_local(impl_def_id) { + // Unmet obligation comes from a `derive` macro, point at it once to + // avoid multiple span labels pointing at the same place. + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }), + .. + })) if matches!( + self_ty.span.ctxt().outer_expn_data().kind, + ExpnKind::Macro(MacroKind::Derive, _) + ) || matches!( + of_trait.as_ref().map(|t| t.path.span.ctxt().outer_expn_data().kind), + Some(ExpnKind::Macro(MacroKind::Derive, _)) + ) => + { + let span = self_ty.span.ctxt().outer_expn_data().call_site; + let mut spans: MultiSpan = span.into(); + spans.push_span_label(span, derive_msg); + let entry = spanned_predicates.entry(spans); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + } + + // Unmet obligation coming from an `impl`. + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }), + span: item_span, + .. + })) => { + let sized_pred = + unsatisfied_predicates.iter().any(|(pred, _, _)| { + match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { + Some(pred.def_id()) == self.tcx.lang_items().sized_trait() + && pred.polarity == ty::ImplPolarity::Positive + } + _ => false, + } + }); + for param in generics.params { + if param.span == cause.span && sized_pred { + let (sp, sugg) = match param.colon_span { + Some(sp) => (sp.shrink_to_hi(), " ?Sized +"), + None => (param.span.shrink_to_hi(), ": ?Sized"), + }; + err.span_suggestion_verbose( + sp, + "consider relaxing the type parameter's implicit \ + `Sized` bound", + sugg, + Applicability::MachineApplicable, + ); + } + } + if let Some(pred) = parent_p { + // Done to add the "doesn't satisfy" `span_label`. + let _ = format_pred(*pred); + } + skip_list.insert(p); + let mut spans = if cause.span != *item_span { + let mut spans: MultiSpan = cause.span.into(); + spans.push_span_label(cause.span, unsatisfied_msg); + spans + } else { + let mut spans = Vec::with_capacity(2); + if let Some(trait_ref) = of_trait { + spans.push(trait_ref.path.span); + } + spans.push(self_ty.span); + spans.into() + }; + if let Some(trait_ref) = of_trait { + spans.push_span_label(trait_ref.path.span, ""); + } + spans.push_span_label(self_ty.span, ""); + + let entry = spanned_predicates.entry(spans); + entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); + } + Some(_) => unreachable!(), + None => (), + } + } + let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); + spanned_predicates.sort_by_key(|(span, (_, _, _))| span.primary_span()); + for (span, (_path, _self_ty, preds)) in spanned_predicates { + let mut preds: Vec<_> = preds + .into_iter() + .filter_map(|pred| format_pred(*pred)) + .map(|(p, _)| format!("`{}`", p)) + .collect(); + preds.sort(); + preds.dedup(); + let msg = if let [pred] = &preds[..] { + format!("trait bound {} was not satisfied", pred) + } else { + format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),) + }; + err.span_note(span, &msg); + unsatisfied_bounds = true; + } + + // The requirements that didn't have an `impl` span to show. + let mut bound_list = unsatisfied_predicates + .iter() + .filter_map(|(pred, parent_pred, _cause)| { + format_pred(*pred).map(|(p, self_ty)| { + collect_type_param_suggestions(self_ty, *pred, &p); + ( + match parent_pred { + None => format!("`{}`", &p), + Some(parent_pred) => match format_pred(*parent_pred) { + None => format!("`{}`", &p), + Some((parent_p, _)) => { + collect_type_param_suggestions(self_ty, *parent_pred, &p); + format!("`{}`\nwhich is required by `{}`", p, parent_p) + } + }, + }, + *pred, + ) + }) + }) + .filter(|(_, pred)| !skip_list.contains(&pred)) + .map(|(t, _)| t) + .enumerate() + .collect::>(); + + for ((span, add_where_or_comma), obligations) in type_params.into_iter() { + restrict_type_params = true; + // #74886: Sort here so that the output is always the same. + let mut obligations = obligations.into_iter().collect::>(); + obligations.sort(); + err.span_suggestion_verbose( + span, + &format!( + "consider restricting the type parameter{s} to satisfy the \ + trait bound{s}", + s = pluralize!(obligations.len()) + ), + format!("{} {}", add_where_or_comma, obligations.join(", ")), + Applicability::MaybeIncorrect, + ); + } + + bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically. + bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677 + bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order. + + if !bound_list.is_empty() || !skip_list.is_empty() { + let bound_list = + bound_list.into_iter().map(|(_, path)| path).collect::>().join("\n"); + let actual_prefix = rcvr_ty.prefix_string(self.tcx); + info!("unimplemented_traits.len() == {}", unimplemented_traits.len()); + let (primary_message, label) = if unimplemented_traits.len() == 1 + && unimplemented_traits_only + { + unimplemented_traits + .into_iter() + .next() + .map(|(_, (trait_ref, obligation))| { + if trait_ref.self_ty().references_error() || rcvr_ty.references_error() + { + // Avoid crashing. + return (None, None); + } + let OnUnimplementedNote { message, label, .. } = + self.err_ctxt().on_unimplemented_note(trait_ref, &obligation); + (message, label) + }) + .unwrap() + } else { + (None, None) + }; + let primary_message = primary_message.unwrap_or_else(|| format!( + "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" + )); + err.set_primary_message(&primary_message); + if let Some(label) = label { + custom_span_label = true; + err.span_label(span, label); + } + if !bound_list.is_empty() { + err.note(&format!( + "the following trait bounds were not satisfied:\n{bound_list}" + )); + } + self.suggest_derive(&mut err, &unsatisfied_predicates); + + unsatisfied_bounds = true; + } + } + + let label_span_not_found = |err: &mut Diagnostic| { + if unsatisfied_predicates.is_empty() { + err.span_label(span, format!("{item_kind} not found in `{ty_str}`")); + let is_string_or_ref_str = match rcvr_ty.kind() { + ty::Ref(_, ty, _) => { + ty.is_str() + || matches!( + ty.kind(), + ty::Adt(adt, _) if Some(adt.did()) == self.tcx.lang_items().string() + ) + } + ty::Adt(adt, _) => Some(adt.did()) == self.tcx.lang_items().string(), + _ => false, + }; + if is_string_or_ref_str && item_name.name == sym::iter { + err.span_suggestion_verbose( + item_name.span, + "because of the in-memory representation of `&str`, to obtain \ + an `Iterator` over each of its codepoint use method `chars`", + "chars", + Applicability::MachineApplicable, + ); + } + if let ty::Adt(adt, _) = rcvr_ty.kind() { + let mut inherent_impls_candidate = self + .tcx + .inherent_impls(adt.did()) + .iter() + .copied() + .filter(|def_id| { + if let Some(assoc) = self.associated_value(*def_id, item_name) { + // Check for both mode is the same so we avoid suggesting + // incorrect associated item. + match (mode, assoc.fn_has_self_parameter, source) { + (Mode::MethodCall, true, SelfSource::MethodCall(_)) => { + // We check that the suggest type is actually + // different from the received one + // So we avoid suggestion method with Box + // for instance + self.tcx.at(span).type_of(*def_id) != rcvr_ty + && self.tcx.at(span).type_of(*def_id) != rcvr_ty + } + (Mode::Path, false, _) => true, + _ => false, + } + } else { + false + } + }) + .collect::>(); + if !inherent_impls_candidate.is_empty() { + inherent_impls_candidate.sort(); + inherent_impls_candidate.dedup(); + + // number of type to shows at most. + let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 }; + let type_candidates = inherent_impls_candidate + .iter() + .take(limit) + .map(|impl_item| { + format!("- `{}`", self.tcx.at(span).type_of(*impl_item)) + }) + .collect::>() + .join("\n"); + let additional_types = if inherent_impls_candidate.len() > limit { + format!("\nand {} more types", inherent_impls_candidate.len() - limit) + } else { + "".to_string() + }; + err.note(&format!( + "the {item_kind} was found for\n{}{}", + type_candidates, additional_types + )); + } + } + } else { + err.span_label( + span, + format!( + "{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds" + ), + ); + } + }; + + // If the method name is the name of a field with a function or closure type, + // give a helping note that it has to be called as `(x.f)(...)`. + if let SelfSource::MethodCall(expr) = source { + if !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_name, &mut err) + && lev_candidate.is_none() + && !custom_span_label + { + label_span_not_found(&mut err); + } + } else if !custom_span_label { + label_span_not_found(&mut err); + } + + // Don't suggest (for example) `expr.field.clone()` if `expr.clone()` + // can't be called due to `typeof(expr): Clone` not holding. + if unsatisfied_predicates.is_empty() { + self.suggest_calling_method_on_field(&mut err, source, span, rcvr_ty, item_name); + } + + self.check_for_inner_self(&mut err, source, rcvr_ty, item_name); + + bound_spans.sort(); + bound_spans.dedup(); + for (span, msg) in bound_spans.into_iter() { + err.span_label(span, &msg); + } + + if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params { + } else { + self.suggest_traits_to_import( + &mut err, + span, + rcvr_ty, + item_name, + args.map(|(_, args)| args.len() + 1), + source, + no_match_data.out_of_scope_traits.clone(), + &unsatisfied_predicates, + &static_candidates, + unsatisfied_bounds, + ); + } + + // Don't emit a suggestion if we found an actual method + // that had unsatisfied trait bounds + if unsatisfied_predicates.is_empty() && rcvr_ty.is_enum() { + let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT"); + if let Some(suggestion) = lev_distance::find_best_match_for_name( + &adt_def.variants().iter().map(|s| s.name).collect::>(), + item_name.name, + None, + ) { + err.span_suggestion( + span, + "there is a variant with a similar name", + suggestion, + Applicability::MaybeIncorrect, + ); + } + } + + if item_name.name == sym::as_str && rcvr_ty.peel_refs().is_str() { + let msg = "remove this method call"; + let mut fallback_span = true; + if let SelfSource::MethodCall(expr) = source { + let call_expr = + self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); + if let Some(span) = call_expr.span.trim_start(expr.span) { + err.span_suggestion(span, msg, "", Applicability::MachineApplicable); + fallback_span = false; + } + } + if fallback_span { + err.span_label(span, msg); + } + } else if let Some(lev_candidate) = lev_candidate { + // Don't emit a suggestion if we found an actual method + // that had unsatisfied trait bounds + if unsatisfied_predicates.is_empty() { + let def_kind = lev_candidate.kind.as_def_kind(); + // Methods are defined within the context of a struct and their first parameter is always self, + // which represents the instance of the struct the method is being called on + // Associated functions don’t take self as a parameter and + // they are not methods because they don’t have an instance of the struct to work with. + if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter { + err.span_suggestion( + span, + &format!("there is a method with a similar name",), + lev_candidate.name, + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion( + span, + &format!( + "there is {} {} with a similar name", + def_kind.article(), + def_kind.descr(lev_candidate.def_id), + ), + lev_candidate.name, + Applicability::MaybeIncorrect, + ); + } + } + } + + self.check_for_deref_method(&mut err, source, rcvr_ty, item_name); + return Some(err); + } + + fn note_candidates_on_method_error( + &self, + rcvr_ty: Ty<'tcx>, + item_name: Ident, + args: Option<(&'tcx hir::Expr<'tcx>, &'tcx [hir::Expr<'tcx>])>, + span: Span, + err: &mut Diagnostic, + sources: &mut Vec, + sugg_span: Option, + ) { + sources.sort(); + sources.dedup(); + // Dynamic limit to avoid hiding just one candidate, which is silly. + let limit = if sources.len() == 5 { 5 } else { 4 }; + + for (idx, source) in sources.iter().take(limit).enumerate() { + match *source { + CandidateSource::Impl(impl_did) => { + // Provide the best span we can. Use the item, if local to crate, else + // the impl, if local to crate (item may be defaulted), else nothing. + let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { + let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; + self.associated_value(impl_trait_ref.def_id, item_name) + }) else { + continue; + }; + + let note_span = if item.def_id.is_local() { + Some(self.tcx.def_span(item.def_id)) + } else if impl_did.is_local() { + Some(self.tcx.def_span(impl_did)) + } else { + None + }; + + let impl_ty = self.tcx.at(span).type_of(impl_did); + + let insertion = match self.tcx.impl_trait_ref(impl_did) { + None => String::new(), + Some(trait_ref) => { + format!(" of the trait `{}`", self.tcx.def_path_str(trait_ref.def_id)) + } + }; + + let (note_str, idx) = if sources.len() > 1 { + ( + format!( + "candidate #{} is defined in an impl{} for the type `{}`", + idx + 1, + insertion, + impl_ty, + ), + Some(idx + 1), + ) + } else { + ( + format!( + "the candidate is defined in an impl{} for the type `{}`", + insertion, impl_ty, + ), + None, + ) + }; + if let Some(note_span) = note_span { + // We have a span pointing to the method. Show note with snippet. + err.span_note(note_span, ¬e_str); + } else { + err.note(¬e_str); + } + if let Some(sugg_span) = sugg_span + && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { + let path = self.tcx.def_path_str(trait_ref.def_id); + + let ty = match item.kind { + ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, + ty::AssocKind::Fn => self + .tcx + .fn_sig(item.def_id) + .inputs() + .skip_binder() + .get(0) + .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr()) + .copied() + .unwrap_or(rcvr_ty), + }; + print_disambiguation_help( + item_name, + args, + err, + path, + ty, + item.kind, + item.def_id, + sugg_span, + idx, + self.tcx.sess.source_map(), + item.fn_has_self_parameter, + ); + } + } + CandidateSource::Trait(trait_did) => { + let Some(item) = self.associated_value(trait_did, item_name) else { continue }; + let item_span = self.tcx.def_span(item.def_id); + let idx = if sources.len() > 1 { + let msg = &format!( + "candidate #{} is defined in the trait `{}`", + idx + 1, + self.tcx.def_path_str(trait_did) + ); + err.span_note(item_span, msg); + Some(idx + 1) + } else { + let msg = &format!( + "the candidate is defined in the trait `{}`", + self.tcx.def_path_str(trait_did) + ); + err.span_note(item_span, msg); + None + }; + if let Some(sugg_span) = sugg_span { + let path = self.tcx.def_path_str(trait_did); + print_disambiguation_help( + item_name, + args, + err, + path, + rcvr_ty, + item.kind, + item.def_id, + sugg_span, + idx, + self.tcx.sess.source_map(), + item.fn_has_self_parameter, + ); + } + } + } + } + if sources.len() > limit { + err.note(&format!("and {} others", sources.len() - limit)); + } + } + /// Suggest calling `Ty::method` if `.method()` isn't found because the method /// doesn't take a `self` receiver. fn suggest_associated_call_syntax( From 93e62a4bf629c0904c047e02b79905c70b9abf79 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 27 Dec 2022 19:11:13 +0800 Subject: [PATCH 073/223] resolve merge conflict --- .../rustc_hir_typeck/src/method/suggest.rs | 102 ++++++++++-------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index d391e3182072..71c3803e64fa 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mode = no_match_data.mode; let tcx = self.tcx; let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty); - let ty_str = self.ty_to_string(rcvr_ty); + let ty_str = with_forced_trimmed_paths!(self.ty_to_string(rcvr_ty)); let is_method = mode == Mode::MethodCall; let unsatisfied_predicates = &no_match_data.unsatisfied_predicates; let lev_candidate = no_match_data.lev_candidate; @@ -523,7 +523,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let term = pred.skip_binder().term; let obligation = format!("{} = {}", projection_ty, term); - let quiet = format!("{} = {}", quiet_projection_ty, term); + let quiet = with_forced_trimmed_paths!(format!( + "{} = {}", + quiet_projection_ty, term + )); bound_span_label(projection_ty.self_ty(), &obligation, &quiet); Some((obligation, projection_ty.self_ty())) @@ -533,7 +536,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let self_ty = p.self_ty(); let path = p.print_only_trait_path(); let obligation = format!("{}: {}", self_ty, path); - let quiet = format!("_: {}", path); + let quiet = with_forced_trimmed_paths!(format!("_: {}", path)); bound_span_label(self_ty, &obligation, &quiet); Some((obligation, self_ty)) } @@ -636,6 +639,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let entry = spanned_predicates.entry(spans); entry.or_insert_with(|| (path, tr_self_ty, Vec::new())).2.push(p); } + Some(Node::Item(hir::Item { + kind: hir::ItemKind::Trait(rustc_ast::ast::IsAuto::Yes, ..), + span: item_span, + .. + })) => { + tcx.sess.delay_span_bug( + *item_span, + "auto trait is invoked with no method error, but no error reported?", + ); + } Some(_) => unreachable!(), None => (), } @@ -731,9 +744,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (None, None) }; - let primary_message = primary_message.unwrap_or_else(|| format!( - "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied" - )); + let primary_message = primary_message.unwrap_or_else(|| { + format!( + "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, \ + but its trait bounds were not satisfied" + ) + }); err.set_primary_message(&primary_message); if let Some(label) = label { custom_span_label = true; @@ -826,11 +842,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } else { + let ty_str = + if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") }; err.span_label( span, - format!( - "{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds" - ), + format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"), ); } }; @@ -922,7 +938,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if def_kind == DefKind::AssocFn && lev_candidate.fn_has_self_parameter { err.span_suggestion( span, - &format!("there is a method with a similar name",), + "there is a method with a similar name", lev_candidate.name, Applicability::MaybeIncorrect, ); @@ -966,11 +982,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let Some(item) = self.associated_value(impl_did, item_name).or_else(|| { - let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; - self.associated_value(impl_trait_ref.def_id, item_name) - }) else { - continue; - }; + let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; + self.associated_value(impl_trait_ref.def_id, item_name) + }) else { + continue; + }; let note_span = if item.def_id.is_local() { Some(self.tcx.def_span(item.def_id)) @@ -1015,35 +1031,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.note(¬e_str); } if let Some(sugg_span) = sugg_span - && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { - let path = self.tcx.def_path_str(trait_ref.def_id); + && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) { + let path = self.tcx.def_path_str(trait_ref.def_id); - let ty = match item.kind { - ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, - ty::AssocKind::Fn => self - .tcx - .fn_sig(item.def_id) - .inputs() - .skip_binder() - .get(0) - .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr()) - .copied() - .unwrap_or(rcvr_ty), - }; - print_disambiguation_help( - item_name, - args, - err, - path, - ty, - item.kind, - item.def_id, - sugg_span, - idx, - self.tcx.sess.source_map(), - item.fn_has_self_parameter, - ); - } + let ty = match item.kind { + ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty, + ty::AssocKind::Fn => self + .tcx + .fn_sig(item.def_id) + .inputs() + .skip_binder() + .get(0) + .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr()) + .copied() + .unwrap_or(rcvr_ty), + }; + print_disambiguation_help( + item_name, + args, + err, + path, + ty, + item.kind, + item.def_id, + sugg_span, + idx, + self.tcx.sess.source_map(), + item.fn_has_self_parameter, + ); + } } CandidateSource::Trait(trait_did) => { let Some(item) = self.associated_value(trait_did, item_name) else { continue }; From 1f1dd5f3cc522de86eb0ef5b8df53af0e347f73b Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 16:14:21 +1300 Subject: [PATCH 074/223] pattern destructure `has_test` Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com> --- src/tools/tidy/src/error_codes.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index ac87e4797c59..42d94311d228 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -173,9 +173,7 @@ fn check_error_codes_docs( return; } - // `has_test.0` checks whether the error code has any (potentially untested) code example. - // `has_test.1` checks whether the error code has a proper (definitely tested) doctest. - let has_test = check_explanation_has_doctest(&contents, &err_code); + let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = check_explanation_has_doctest(&contents, &err_code); if has_test.2 { verbose_print!( verbose, From b7341db5d82e93c4257763b33fec853817197078 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Mon, 2 Jan 2023 16:22:18 +1300 Subject: [PATCH 075/223] fix CI --- src/tools/tidy/src/error_codes.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 42d94311d228..938e194abdf0 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -173,22 +173,23 @@ fn check_error_codes_docs( return; } - let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = check_explanation_has_doctest(&contents, &err_code); - if has_test.2 { + let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = + check_explanation_has_doctest(&contents, &err_code); + if emit_ignore_warning { verbose_print!( verbose, "warning: Error code `{err_code}` uses the ignore header. This should not be used, add the error code to the \ `IGNORE_DOCTEST_CHECK` constant instead." ); } - if has_test.3 { + if emit_no_longer_warning { no_longer_emitted_codes.push(err_code.to_owned()); verbose_print!( verbose, "warning: Error code `{err_code}` is no longer emitted and should be removed entirely." ); } - if !has_test.0 { + if !found_code_example { verbose_print!( verbose, "warning: Error code `{err_code}` doesn't have a code example, all error codes are expected to have one \ @@ -196,15 +197,15 @@ fn check_error_codes_docs( ); } - let test_ignored = IGNORE_DOCTEST_CHECK.contains(&err_code); + let test_ignored = IGNORE_DOCTEST_CHECK.contains(&&err_code); // Check that the explanation has a doctest, and if it shouldn't, that it doesn't - if !has_test.1 && !test_ignored { + if !found_proper_doctest && !test_ignored { errors.push(format!( "`{}` doesn't use its own error code in compile_fail example", path.display(), )); - } else if has_test.1 && test_ignored { + } else if found_proper_doctest && test_ignored { errors.push(format!( "`{}` has a compile_fail doctest with its own error code, it shouldn't \ be listed in `IGNORE_DOCTEST_CHECK`", From cafdd2f7bb1be0fa888e0aecafa3adde1a4b5476 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 2 Jan 2023 03:52:29 +0000 Subject: [PATCH 076/223] Note maximum integer literal for `IntLiteralTooLarge` --- compiler/rustc_error_messages/locales/en-US/session.ftl | 1 + compiler/rustc_session/src/errors.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index ab9e8b6baae6..5b4e6fcf9270 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -85,6 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite .help = valid suffixes are `f32` and `f64` session_int_literal_too_large = integer literal is too large + .note = value exceeds limit of 340282366920938463463374607431768211455 session_invalid_int_literal_width = invalid width `{$width}` for integer literal .help = valid widths are 8, 16, 32, 64 and 128 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e72b76cfee9e..effb561688c2 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -260,6 +260,7 @@ pub(crate) struct InvalidFloatLiteralSuffix { #[derive(Diagnostic)] #[diag(session_int_literal_too_large)] +#[note] pub(crate) struct IntLiteralTooLarge { #[primary_span] pub span: Span, From 32ab2d95f1538d50434cb833348fc7c19527bcba Mon Sep 17 00:00:00 2001 From: Gimbles <93856041+gimbles@users.noreply.github.com> Date: Mon, 2 Jan 2023 15:51:54 +0530 Subject: [PATCH 077/223] Update format.rs --- compiler/rustc_builtin_macros/src/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 63bc0d552c11..b2b7b9d75bd3 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -638,7 +638,7 @@ fn report_missing_placeholders( if show_doc_note { diag.note(concat!( stringify!($kind), - " formatting not supported; see the documentation for `std::fmt`", + " formatting is not supported; see the documentation for `std::fmt`", )); } if suggestions.len() > 0 { From f8755ab864a271a7cc2c4e6cdd8ad0f7cf8e64e1 Mon Sep 17 00:00:00 2001 From: gimbles Date: Mon, 2 Jan 2023 16:53:43 +0530 Subject: [PATCH 078/223] maybe --- src/test/ui/fmt/ifmt-bad-arg.stderr | 2 +- src/test/ui/fmt/issue-89173.rs | 2 +- src/test/ui/fmt/issue-89173.stderr | 2 +- src/test/ui/macros/format-foreign.stderr | 10 +++++----- src/test/ui/macros/format-unused-lables.stderr | 2 +- src/test/ui/macros/issue-92267.stderr | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index a8a2a47fe46e..c2619d6df58b 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -170,7 +170,7 @@ LL | format!("foo %s baz", "bar"); | | | help: format specifiers use curly braces: `{}` | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: invalid format string: expected `'}'`, found `'t'` --> $DIR/ifmt-bad-arg.rs:75:1 diff --git a/src/test/ui/fmt/issue-89173.rs b/src/test/ui/fmt/issue-89173.rs index 96277d4d0d9d..fc99af408592 100644 --- a/src/test/ui/fmt/issue-89173.rs +++ b/src/test/ui/fmt/issue-89173.rs @@ -10,5 +10,5 @@ fn main() { //~| NOTE: argument never used //~| NOTE: argument never used //~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width - //~| NOTE: printf formatting not supported + //~| NOTE: printf formatting is not supported } diff --git a/src/test/ui/fmt/issue-89173.stderr b/src/test/ui/fmt/issue-89173.stderr index 7b21e0a4fc89..ddeb769eadc5 100644 --- a/src/test/ui/fmt/issue-89173.stderr +++ b/src/test/ui/fmt/issue-89173.stderr @@ -12,7 +12,7 @@ note: format specifiers use curly braces, and you have to use a positional or na | LL | print!("%0*x", width, num); | ^^^^ - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: aborting due to previous error diff --git a/src/test/ui/macros/format-foreign.stderr b/src/test/ui/macros/format-foreign.stderr index ff5236dc949b..7971c2ab2b9b 100644 --- a/src/test/ui/macros/format-foreign.stderr +++ b/src/test/ui/macros/format-foreign.stderr @@ -8,7 +8,7 @@ LL | println!("%.*3$s %s!\n", "Hello,", "World", 4); | | argument never used | multiple missing formatting specifiers | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL | println!("{:.2$} {}!\n", "Hello,", "World", 4); @@ -22,7 +22,7 @@ LL | println!("%1$*2$.*3$f", 123.456); | | | help: format specifiers use curly braces: `{0:1$.2$}` | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: multiple unused formatting arguments --> $DIR/format-foreign.rs:6:7 @@ -37,7 +37,7 @@ LL | | "###, "Hello,", "World", 4); | |____| argument never used | multiple missing formatting specifiers | - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL ~ println!(r###"{:.2$} @@ -60,7 +60,7 @@ LL | println!("Hi there, $NAME.", NAME="Tim"); | | | help: format specifiers use curly braces: `{NAME}` | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` error: multiple unused formatting arguments --> $DIR/format-foreign.rs:15:32 @@ -72,7 +72,7 @@ LL | println!("$1 $0 $$ $NAME", 1, 2, NAME=3); | | argument never used | multiple missing formatting specifiers | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` help: format specifiers use curly braces | LL | println!("{1} {0} $$ {NAME}", 1, 2, NAME=3); diff --git a/src/test/ui/macros/format-unused-lables.stderr b/src/test/ui/macros/format-unused-lables.stderr index 7423c7b7c8b4..fad87fa2aeea 100644 --- a/src/test/ui/macros/format-unused-lables.stderr +++ b/src/test/ui/macros/format-unused-lables.stderr @@ -44,7 +44,7 @@ LL | "things" LL | , UNUSED="args"); | ^^^^^^ named argument never used | - = note: shell formatting not supported; see the documentation for `std::fmt` + = note: shell formatting is not supported; see the documentation for `std::fmt` error: aborting due to 4 previous errors diff --git a/src/test/ui/macros/issue-92267.stderr b/src/test/ui/macros/issue-92267.stderr index d2d66c81198e..5359f68cd551 100644 --- a/src/test/ui/macros/issue-92267.stderr +++ b/src/test/ui/macros/issue-92267.stderr @@ -10,7 +10,7 @@ note: format specifiers use curly braces, and the conversion specifier ` | LL | pub fn main() { println!("🦀%%%", 0) } | ^^ - = note: printf formatting not supported; see the documentation for `std::fmt` + = note: printf formatting is not supported; see the documentation for `std::fmt` error: aborting due to previous error From 537c7f4fa95f4c5b0a6259ee7badae5ad57d0940 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Mon, 2 Jan 2023 05:07:02 +0000 Subject: [PATCH 079/223] Print correct base for too-large literals Also update tests --- compiler/rustc_ast/src/util/literal.rs | 4 +- .../locales/en-US/session.ftl | 2 +- compiler/rustc_session/src/errors.rs | 12 ++- src/test/ui/lexer/error-stage.stderr | 2 + src/test/ui/lexer/lex-bad-numeric-literals.rs | 8 ++ .../ui/lexer/lex-bad-numeric-literals.stderr | 84 ++++++++++++------- ...104769-concat_bytes-invalid-literal.stderr | 2 + .../parser/int-literal-too-large-span.stderr | 2 + src/test/ui/parser/issues/issue-5544-a.stderr | 2 + src/test/ui/parser/issues/issue-5544-b.stderr | 2 + 10 files changed, 87 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 0daeecb53a8b..69a9a5830483 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -34,7 +34,7 @@ pub enum LitError { InvalidIntSuffix, InvalidFloatSuffix, NonDecimalFloat(u32), - IntTooLarge, + IntTooLarge(u32), } impl LitKind { @@ -333,6 +333,6 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge } + if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } }) } diff --git a/compiler/rustc_error_messages/locales/en-US/session.ftl b/compiler/rustc_error_messages/locales/en-US/session.ftl index 5b4e6fcf9270..bc37d91a7c6a 100644 --- a/compiler/rustc_error_messages/locales/en-US/session.ftl +++ b/compiler/rustc_error_messages/locales/en-US/session.ftl @@ -85,7 +85,7 @@ session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float lite .help = valid suffixes are `f32` and `f64` session_int_literal_too_large = integer literal is too large - .note = value exceeds limit of 340282366920938463463374607431768211455 + .note = value exceeds limit of `{$limit}` session_invalid_int_literal_width = invalid width `{$width}` for integer literal .help = valid widths are 8, 16, 32, 64 and 128 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index effb561688c2..f5a72573d58c 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -264,6 +264,7 @@ pub(crate) struct InvalidFloatLiteralSuffix { pub(crate) struct IntLiteralTooLarge { #[primary_span] pub span: Span, + pub limit: String, } #[derive(Diagnostic)] @@ -362,8 +363,15 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: _ => unreachable!(), }; } - LitError::IntTooLarge => { - sess.emit_err(IntLiteralTooLarge { span }); + LitError::IntTooLarge(base) => { + let max = u128::MAX; + let limit = match base { + 2 => format!("{max:#b}"), + 8 => format!("{max:#o}"), + 16 => format!("{max:#x}"), + _ => format!("{max}"), + }; + sess.emit_err(IntLiteralTooLarge { span, limit }); } } } diff --git a/src/test/ui/lexer/error-stage.stderr b/src/test/ui/lexer/error-stage.stderr index 697a7c28da16..ecbdb14dc868 100644 --- a/src/test/ui/lexer/error-stage.stderr +++ b/src/test/ui/lexer/error-stage.stderr @@ -49,6 +49,8 @@ error: integer literal is too large | LL | 999340282366920938463463374607431768211455999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to 8 previous errors diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.rs b/src/test/ui/lexer/lex-bad-numeric-literals.rs index cf8440ca488c..56bdc50e40d6 100644 --- a/src/test/ui/lexer/lex-bad-numeric-literals.rs +++ b/src/test/ui/lexer/lex-bad-numeric-literals.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + fn main() { 0o1.0; //~ ERROR: octal float literal is not supported 0o2f32; //~ ERROR: octal float literal is not supported @@ -15,6 +17,12 @@ fn main() { //~^ ERROR: integer literal is too large 9900000000000000000000000000999999999999999999999999999999; //~^ ERROR: integer literal is too large + 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + //~^ ERROR: integer literal is too large + 0o37777777777777777777777777777777777777777770; + //~^ ERROR: integer literal is too large + 0xffffffffffffffffffffffffffffffff0; + //~^ ERROR: integer literal is too large 0x; //~ ERROR: no valid digits 0xu32; //~ ERROR: no valid digits 0ou32; //~ ERROR: no valid digits diff --git a/src/test/ui/lexer/lex-bad-numeric-literals.stderr b/src/test/ui/lexer/lex-bad-numeric-literals.stderr index f05d61603023..1457541970af 100644 --- a/src/test/ui/lexer/lex-bad-numeric-literals.stderr +++ b/src/test/ui/lexer/lex-bad-numeric-literals.stderr @@ -1,141 +1,169 @@ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:2:5 + --> $DIR/lex-bad-numeric-literals.rs:4:5 | LL | 0o1.0; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:4:5 + --> $DIR/lex-bad-numeric-literals.rs:6:5 | LL | 0o3.0f32; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:5:5 + --> $DIR/lex-bad-numeric-literals.rs:7:5 | LL | 0o4e4; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:6:5 + --> $DIR/lex-bad-numeric-literals.rs:8:5 | LL | 0o5.0e5; | ^^^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:7:5 + --> $DIR/lex-bad-numeric-literals.rs:9:5 | LL | 0o6e6f32; | ^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:8:5 + --> $DIR/lex-bad-numeric-literals.rs:10:5 | LL | 0o7.0e7f64; | ^^^^^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:9:5 + --> $DIR/lex-bad-numeric-literals.rs:11:5 | LL | 0x8.0e+9; | ^^^^^^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:10:5 + --> $DIR/lex-bad-numeric-literals.rs:12:5 | LL | 0x9.0e-9; | ^^^^^^^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:11:5 + --> $DIR/lex-bad-numeric-literals.rs:13:5 | LL | 0o; | ^^ error: expected at least one digit in exponent - --> $DIR/lex-bad-numeric-literals.rs:12:5 + --> $DIR/lex-bad-numeric-literals.rs:14:5 | LL | 1e+; | ^^^ error: hexadecimal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:13:5 + --> $DIR/lex-bad-numeric-literals.rs:15:5 | LL | 0x539.0; | ^^^^^^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:18:5 + --> $DIR/lex-bad-numeric-literals.rs:26:5 | LL | 0x; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:19:5 + --> $DIR/lex-bad-numeric-literals.rs:27:5 | LL | 0xu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:20:5 + --> $DIR/lex-bad-numeric-literals.rs:28:5 | LL | 0ou32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:21:5 + --> $DIR/lex-bad-numeric-literals.rs:29:5 | LL | 0bu32; | ^^ error[E0768]: no valid digits found for number - --> $DIR/lex-bad-numeric-literals.rs:22:5 + --> $DIR/lex-bad-numeric-literals.rs:30:5 | LL | 0b; | ^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:24:5 + --> $DIR/lex-bad-numeric-literals.rs:32:5 | LL | 0o123.456; | ^^^^^^^^^ error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:26:5 + --> $DIR/lex-bad-numeric-literals.rs:34:5 | LL | 0b111.101; | ^^^^^^^^^ error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:3:5 + --> $DIR/lex-bad-numeric-literals.rs:5:5 | LL | 0o2f32; | ^^^^^^ not supported -error: integer literal is too large - --> $DIR/lex-bad-numeric-literals.rs:14:5 - | -LL | 9900000000000000000000000000999999999999999999999999999999; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: integer literal is too large --> $DIR/lex-bad-numeric-literals.rs:16:5 | LL | 9900000000000000000000000000999999999999999999999999999999; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:18:5 + | +LL | 9900000000000000000000000000999999999999999999999999999999; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:20:5 + | +LL | 0b111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:22:5 + | +LL | 0o37777777777777777777777777777777777777777770; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0o3777777777777777777777777777777777777777777` + +error: integer literal is too large + --> $DIR/lex-bad-numeric-literals.rs:24:5 + | +LL | 0xffffffffffffffffffffffffffffffff0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` error: octal float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:23:5 + --> $DIR/lex-bad-numeric-literals.rs:31:5 | LL | 0o123f64; | ^^^^^^^^ not supported error: binary float literal is not supported - --> $DIR/lex-bad-numeric-literals.rs:25:5 + --> $DIR/lex-bad-numeric-literals.rs:33:5 | LL | 0b101f64; | ^^^^^^^^ not supported -error: aborting due to 23 previous errors +error: aborting due to 26 previous errors For more information about this error, try `rustc --explain E0768`. diff --git a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr index 8d70faa494db..8807279c27f9 100644 --- a/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr +++ b/src/test/ui/macros/issue-104769-concat_bytes-invalid-literal.stderr @@ -11,6 +11,8 @@ error: integer literal is too large | LL | concat_bytes!(888888888888888888888888888888888888888); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/int-literal-too-large-span.stderr b/src/test/ui/parser/int-literal-too-large-span.stderr index 7cae85fc9fe6..49d6aa5eff8c 100644 --- a/src/test/ui/parser/int-literal-too-large-span.stderr +++ b/src/test/ui/parser/int-literal-too-large-span.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-5544-a.stderr b/src/test/ui/parser/issues/issue-5544-a.stderr index de579c3c134e..6e68c75850af 100644 --- a/src/test/ui/parser/issues/issue-5544-a.stderr +++ b/src/test/ui/parser/issues/issue-5544-a.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | let __isize = 340282366920938463463374607431768211456; // 2^128 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `340282366920938463463374607431768211455` error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-5544-b.stderr b/src/test/ui/parser/issues/issue-5544-b.stderr index 7df212dedfed..5d0e76d5d944 100644 --- a/src/test/ui/parser/issues/issue-5544-b.stderr +++ b/src/test/ui/parser/issues/issue-5544-b.stderr @@ -3,6 +3,8 @@ error: integer literal is too large | LL | let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: value exceeds limit of `0xffffffffffffffffffffffffffffffff` error: aborting due to previous error From 5974f6f0a53614e82df9430b95bcb6e9473265fa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Dec 2022 16:32:08 +0100 Subject: [PATCH 080/223] default OOM handler: use non-unwinding panic (unless -Zoom=panic is set), to match std handler --- library/alloc/src/alloc.rs | 15 ++++++++++++++- library/alloc/src/lib.rs | 1 + library/core/src/panicking.rs | 23 +++++++++++++++++------ library/std/src/alloc.rs | 2 +- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index e5fbfc55761f..e1c612c5b3f1 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -402,7 +402,20 @@ pub mod __alloc_error_handler { // `#[alloc_error_handler]`. #[rustc_std_internal_symbol] pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! { - panic!("memory allocation of {size} bytes failed") + extern "Rust" { + // This symbol is emitted by rustc next to __rust_alloc_error_handler. + // Its value depends on the -Zoom={panic,abort} compiler option. + static __rust_alloc_error_handler_should_panic: u8; + } + + #[allow(unused_unsafe)] + if unsafe { __rust_alloc_error_handler_should_panic != 0 } { + panic!("memory allocation of {size} bytes failed") + } else { + core::panicking::panic_nounwind_fmt(format_args!( + "memory allocation of {size} bytes failed" + )) + } } #[cfg(bootstrap)] diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 96960d43f582..2a7edc2add12 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -110,6 +110,7 @@ #![feature(const_maybe_uninit_as_mut_ptr)] #![feature(const_refs_to_cell)] #![feature(core_intrinsics)] +#![feature(core_panic)] #![feature(const_eval_select)] #![feature(const_pin)] #![feature(const_waker)] diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 9fce78d076bf..36b43ec2181e 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -64,13 +64,17 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { unsafe { panic_impl(&pi) } } -/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize. -/// (No `fmt` variant as a `fmt::Arguments` needs more space to be passed.) +/// Like `panic_fmt`, but for non-unwinding panics. +/// +/// Has to be a separate function so that it can carry the `rustc_nounwind` attribute. #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] -#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics +#[track_caller] +// This attribute has the key side-effect that if the panic handler ignores `can_unwind` +// and unwinds anyway, we will hit the "unwinding out of nounwind function" guard, +// which causes a "panic in a function that cannot unwind". #[rustc_nounwind] -pub fn panic_nounwind(msg: &'static str) -> ! { +pub fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { super::intrinsics::abort() } @@ -83,8 +87,6 @@ pub fn panic_nounwind(msg: &'static str) -> ! { } // PanicInfo with the `can_unwind` flag set to false forces an abort. - let pieces = [msg]; - let fmt = fmt::Arguments::new_v1(&pieces, &[]); let pi = PanicInfo::internal_constructor(Some(&fmt), Location::caller(), false); // SAFETY: `panic_impl` is defined in safe Rust code and thus is safe to call. @@ -112,6 +114,15 @@ pub const fn panic(expr: &'static str) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[])); } +/// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize. +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] +#[cfg_attr(feature = "panic_immediate_abort", inline)] +#[cfg_attr(not(bootstrap), lang = "panic_nounwind")] // needed by codegen for non-unwinding panics +#[rustc_nounwind] +pub fn panic_nounwind(expr: &'static str) -> ! { + panic_nounwind_fmt(fmt::Arguments::new_v1(&[expr], &[])); +} + #[inline] #[track_caller] #[rustc_diagnostic_item = "panic_str"] diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 61c1ff578b2c..c5a5991cc81c 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -338,7 +338,7 @@ fn default_alloc_error_hook(layout: Layout) { #[allow(unused_unsafe)] if unsafe { __rust_alloc_error_handler_should_panic != 0 } { - panic!("memory allocation of {} bytes failed\n", layout.size()); + panic!("memory allocation of {} bytes failed", layout.size()); } else { rtprintpanic!("memory allocation of {} bytes failed\n", layout.size()); } From c00ab4b2de2b5a321476244a9316d4dd3d8f8242 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Tue, 3 Jan 2023 08:44:57 +1300 Subject: [PATCH 081/223] print highest error code --- src/tools/tidy/src/error_codes.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index 938e194abdf0..fdc9d7899059 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -51,6 +51,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut // Stage 1: create list let error_codes = extract_error_codes(root_path, &mut errors, verbose); println!("Found {} error codes", error_codes.len()); + println!("Highest error code: `{}`", error_codes.iter().max().unwrap()); // Stage 2: check list has docs let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose); From 817cc3344677d4dcab7798cb1f191d9b3a760d15 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Mon, 2 Jan 2023 13:12:45 -0700 Subject: [PATCH 082/223] rustdoc: remove legacy box-sizing CSS According to [caniuse], these vendor prefixes aren't needed in any supported web browsers as defined in [RFC 1985] * The last version of Chrome that required a vendor prefix was version 9. The current version is 108. * Firefox 28 is the last version that required a vendor prefix. The [current Firefox ESR] is version 102. * The last version of Safari that required a vendor prefix was version 5. The current version is 16. * The last version of Safari/iOS that required a vendor prefix was version 4. The current version is 16. * Edge never required vendor prefixes. * UCAndroid never required vendor prefixes. [caniuse]: https://caniuse.com/?search=box-sizing [RFC 1985]: https://rust-lang.github.io/rfcs/1985-tiered-browser-support.html [current Firefox ESR]: https://wiki.mozilla.org/Releases --- src/librustdoc/html/static/css/rustdoc.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index bc0458bcd28f..6f8a306d665b 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -76,8 +76,6 @@ } * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; box-sizing: border-box; } From 357c3cf72cfa7f4455ae71ad62816dfcc843746b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Mon, 2 Jan 2023 00:00:00 +0000 Subject: [PATCH 083/223] Fix handling of dead unwinds in backward analyses Dead unwinds set contains a head of an unreachable unwind edge. --- compiler/rustc_mir_dataflow/src/framework/direction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 5ff6b9e7e69b..077a21fc8afc 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -287,7 +287,7 @@ impl Direction for Backward { | mir::TerminatorKind::InlineAsm { cleanup: Some(unwind), .. } if unwind == bb => { - if dead_unwinds.map_or(true, |dead| !dead.contains(bb)) { + if dead_unwinds.map_or(true, |dead| !dead.contains(pred)) { propagate(pred, exit_state); } } From eb53eea60920e28d3c3e053b170d015be7493a74 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 29 Dec 2022 21:08:09 +0000 Subject: [PATCH 084/223] Add json output to `-Zdump-mono-stats` This allows analyzing the output programatically; for example, finding the item with the highest `total_estimate`. I also took the liberty of adding `untracked` tests to `rustc_session` and documentation to the unstable book for `dump-mono-items`. --- Cargo.lock | 2 + compiler/rustc_interface/src/tests.rs | 12 +++-- compiler/rustc_monomorphize/Cargo.toml | 2 + .../src/partitioning/mod.rs | 48 ++++++++++++------- compiler/rustc_session/src/config.rs | 18 +++++++ compiler/rustc_session/src/options.rs | 20 +++++++- .../compiler-flags/dump-mono-stats-format.md | 6 +++ .../src/compiler-flags/dump-mono-stats.md | 14 ++++++ src/test/run-make/dump-mono-stats/Makefile | 5 ++ src/test/run-make/dump-mono-stats/foo.rs | 1 + src/test/rustdoc-ui/z-help.stdout | 3 +- 11 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md create mode 100644 src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md create mode 100644 src/test/run-make/dump-mono-stats/Makefile create mode 100644 src/test/run-make/dump-mono-stats/foo.rs diff --git a/Cargo.lock b/Cargo.lock index 9581099c210e..9037feec79eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4226,6 +4226,8 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", + "serde", + "serde_json", "smallvec", "tracing", ] diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index ff2196d58577..947d8e80cb0d 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -3,17 +3,16 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; -use rustc_session::config::InstrumentCoverage; -use rustc_session::config::Strip; +use rustc_session::config::rustc_optgroups; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; -use rustc_session::config::{ - rustc_optgroups, ErrorOutputType, ExternLocation, LocationDetail, Options, Passes, -}; use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet, ProcMacroExecutionStrategy, SymbolManglingVersion, WasiExecModel, }; use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{DumpMonoStatsFormat, MirSpanview}; +use rustc_session::config::{ErrorOutputType, ExternLocation, LocationDetail, Options, Strip}; +use rustc_session::config::{InstrumentCoverage, Passes}; use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; @@ -647,6 +646,9 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); + untracked!(dump_mir_spanview, Some(MirSpanview::Statement)); + untracked!(dump_mono_stats, SwitchWithOptPath::Enabled(Some("mono-items-dir/".into()))); + untracked!(dump_mono_stats_format, DumpMonoStatsFormat::Json); untracked!(dylib_lto, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index 6ee5330b63f5..c8af10576b42 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -6,6 +6,8 @@ edition = "2021" [lib] [dependencies] +serde = "1" +serde_json = "1" smallvec = { version = "1.8.1", features = [ "union", "may_dangle" ] } tracing = "0.1" rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 4f25fc71314e..f0417b06a04a 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -109,7 +109,7 @@ use rustc_middle::mir::mono::{CodegenUnit, Linkage}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::query::Providers; use rustc_middle::ty::TyCtxt; -use rustc_session::config::SwitchWithOptPath; +use rustc_session::config::{DumpMonoStatsFormat, SwitchWithOptPath}; use rustc_span::symbol::Symbol; use crate::collector::InliningMap; @@ -492,9 +492,11 @@ fn dump_mono_items_stats<'tcx>( Path::new(".") }; - let filename = format!("{}.mono_items.md", crate_name.unwrap_or("unknown-crate")); + let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format; + let ext = format.extension(); + let filename = format!("{}.mono_items.{ext}", crate_name.unwrap_or("unknown-crate")); let output_path = output_directory.join(&filename); - let file = File::create(output_path)?; + let file = File::create(&output_path)?; let mut file = BufWriter::new(file); // Gather instantiated mono items grouped by def_id @@ -508,30 +510,44 @@ fn dump_mono_items_stats<'tcx>( } } + #[derive(serde::Serialize)] + struct MonoItem { + name: String, + instantiation_count: usize, + size_estimate: usize, + total_estimate: usize, + } + // Output stats sorted by total instantiated size, from heaviest to lightest let mut stats: Vec<_> = items_per_def_id .into_iter() .map(|(def_id, items)| { + let name = with_no_trimmed_paths!(tcx.def_path_str(def_id)); let instantiation_count = items.len(); let size_estimate = items[0].size_estimate(tcx); let total_estimate = instantiation_count * size_estimate; - (def_id, instantiation_count, size_estimate, total_estimate) + MonoItem { name, instantiation_count, size_estimate, total_estimate } }) .collect(); - stats.sort_unstable_by_key(|(_, _, _, total_estimate)| cmp::Reverse(*total_estimate)); + stats.sort_unstable_by_key(|item| cmp::Reverse(item.total_estimate)); if !stats.is_empty() { - writeln!( - file, - "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" - )?; - writeln!(file, "| --- | ---: | ---: | ---: |")?; - for (def_id, instantiation_count, size_estimate, total_estimate) in stats { - let item = with_no_trimmed_paths!(tcx.def_path_str(def_id)); - writeln!( - file, - "| {item} | {instantiation_count} | {size_estimate} | {total_estimate} |" - )?; + match format { + DumpMonoStatsFormat::Json => serde_json::to_writer(file, &stats)?, + DumpMonoStatsFormat::Markdown => { + writeln!( + file, + "| Item | Instantiation count | Estimated Cost Per Instantiation | Total Estimated Cost |" + )?; + writeln!(file, "| --- | ---: | ---: | ---: |")?; + + for MonoItem { name, instantiation_count, size_estimate, total_estimate } in stats { + writeln!( + file, + "| `{name}` | {instantiation_count} | {size_estimate} | {total_estimate} |" + )?; + } + } } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 3bafd3730bd7..f3758cd7d27b 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2975,3 +2975,21 @@ pub enum ProcMacroExecutionStrategy { /// Run the proc-macro code on a different thread. CrossThread, } + +/// Which format to use for `-Z dump-mono-stats` +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum DumpMonoStatsFormat { + /// Pretty-print a markdown table + Markdown, + /// Emit structured JSON + Json, +} + +impl DumpMonoStatsFormat { + pub fn extension(self) -> &'static str { + match self { + Self::Markdown => "md", + Self::Json => "json", + } + } +} diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ae01efebacc2..7ff667ecb2cd 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -377,6 +377,7 @@ mod desc { pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavorCli::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; + pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; @@ -820,6 +821,21 @@ mod parse { true } + pub(crate) fn parse_dump_mono_stats(slot: &mut DumpMonoStatsFormat, v: Option<&str>) -> bool { + match v { + None => true, + Some("json") => { + *slot = DumpMonoStatsFormat::Json; + true + } + Some("markdown") => { + *slot = DumpMonoStatsFormat::Markdown; + true + } + Some(_) => false, + } + } + pub(crate) fn parse_instrument_coverage( slot: &mut Option, v: Option<&str>, @@ -1295,7 +1311,9 @@ options! { an additional `.html` file showing the computed coverage spans."), dump_mono_stats: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], - "output statistics about monomorphization collection (format: markdown)"), + "output statistics about monomorphization collection"), + dump_mono_stats_format: DumpMonoStatsFormat = (DumpMonoStatsFormat::Markdown, parse_dump_mono_stats, [UNTRACKED], + "the format to use for -Z dump-mono-stats (`markdown` (default) or `json`)"), dwarf_version: Option = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), dylib_lto: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md new file mode 100644 index 000000000000..a497a75261fe --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats-format.md @@ -0,0 +1,6 @@ +# `dump-mono-stats-format` + +-------------------- + +The `-Z dump-mono-stats-format` compiler flag controls what file format to use for `-Z dump-mono-stats`. +The default is markdown; currently JSON is also supported. JSON can be useful for programatically manipulating the results (e.g. to find the item that took the longest to compile). diff --git a/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md new file mode 100644 index 000000000000..4c8bc8b45789 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dump-mono-stats.md @@ -0,0 +1,14 @@ +# `dump-mono-stats` + +-------------------- + +The `-Z dump-mono-stats` compiler flag generates a file with a list of the monomorphized items in the current crate. +It is useful for investigating compile times. + +It accepts an optional directory where the file will be located. If no directory is specified, the file will be placed in the current directory. + +See also `-Z dump-mono-stats-format` and `-Z print-mono-items`. Unlike `print-mono-items`, +`dump-mono-stats` aggregates monomorphized items by definition and includes a size estimate of how +large the item is when codegened. + +See for an overview of monomorphized items. diff --git a/src/test/run-make/dump-mono-stats/Makefile b/src/test/run-make/dump-mono-stats/Makefile new file mode 100644 index 000000000000..fe1112fb0a4a --- /dev/null +++ b/src/test/run-make/dump-mono-stats/Makefile @@ -0,0 +1,5 @@ +include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) --crate-type lib foo.rs -Z dump-mono-stats=$(TMPDIR) -Zdump-mono-stats-format=json + cat $(TMPDIR)/foo.mono_items.json | $(CGREP) '"name":"bar"' diff --git a/src/test/run-make/dump-mono-stats/foo.rs b/src/test/run-make/dump-mono-stats/foo.rs new file mode 100644 index 000000000000..c5c0bc606cd6 --- /dev/null +++ b/src/test/run-make/dump-mono-stats/foo.rs @@ -0,0 +1 @@ +pub fn bar() {} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 53677b183770..9bd6c5fedf54 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -35,7 +35,8 @@ -Z dump-mir-exclude-pass-number=val -- exclude the pass number when dumping MIR (used in tests) (default: no) -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. - -Z dump-mono-stats=val -- output statistics about monomorphization collection (format: markdown) + -Z dump-mono-stats=val -- output statistics about monomorphization collection + -Z dump-mono-stats-format=val -- the format to use for -Z dump-mono-stats (`markdown` (default) or `json`) -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform) -Z dylib-lto=val -- enables LTO for dylib crate type -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) From 5c79624bfaf28540b739f33ffe9d2d1f132555d2 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 29 Dec 2022 21:53:13 +0000 Subject: [PATCH 085/223] Fix `unknown_crate` when `--crate-name` isn't passed on the CLI --- compiler/rustc_monomorphize/src/partitioning/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index f0417b06a04a..97fbb458e792 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -102,7 +102,7 @@ use std::path::{Path, PathBuf}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync; -use rustc_hir::def_id::DefIdSet; +use rustc_hir::def_id::{DefIdSet, LOCAL_CRATE}; use rustc_middle::mir; use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::{CodegenUnit, Linkage}; @@ -417,7 +417,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co // Output monomorphization stats per def_id if let SwitchWithOptPath::Enabled(ref path) = tcx.sess.opts.unstable_opts.dump_mono_stats { if let Err(err) = - dump_mono_items_stats(tcx, &codegen_units, path, tcx.sess.opts.crate_name.as_deref()) + dump_mono_items_stats(tcx, &codegen_units, path, tcx.crate_name(LOCAL_CRATE)) { tcx.sess.emit_fatal(CouldntDumpMonoStats { error: err.to_string() }); } @@ -483,7 +483,7 @@ fn dump_mono_items_stats<'tcx>( tcx: TyCtxt<'tcx>, codegen_units: &[CodegenUnit<'tcx>], output_directory: &Option, - crate_name: Option<&str>, + crate_name: Symbol, ) -> Result<(), Box> { let output_directory = if let Some(ref directory) = output_directory { fs::create_dir_all(directory)?; @@ -494,7 +494,7 @@ fn dump_mono_items_stats<'tcx>( let format = tcx.sess.opts.unstable_opts.dump_mono_stats_format; let ext = format.extension(); - let filename = format!("{}.mono_items.{ext}", crate_name.unwrap_or("unknown-crate")); + let filename = format!("{crate_name}.mono_items.{ext}"); let output_path = output_directory.join(&filename); let file = File::create(&output_path)?; let mut file = BufWriter::new(file); From 2a7d5599706f127c1ebe6e5f992f9245d7f09b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lanteri=20Thauvin?= Date: Mon, 26 Dec 2022 18:49:19 +0100 Subject: [PATCH 086/223] Don't trim path for `unsafe_op_in_unsafe_fn` lints --- .../rustc_mir_build/src/check_unsafety.rs | 23 +++++++++++-------- src/test/ui/unsafe/auxiliary/issue-106126.rs | 9 ++++++++ .../ui/unsafe/issue-106126-good-path-bug.rs | 12 ++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/unsafe/auxiliary/issue-106126.rs create mode 100644 src/test/ui/unsafe/issue-106126-good-path-bug.rs diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 3c311729a52a..03a7f2d70fae 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -5,6 +5,7 @@ use rustc_middle::thir::visit::{self, Visitor}; use rustc_hir as hir; use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; @@ -524,17 +525,19 @@ impl UnsafeOpKind { hir_id: hir::HirId, span: Span, ) { + // FIXME: ideally we would want to trim the def paths, but this is not + // feasible with the current lint emission API (see issue #106126). match self { - CallToUnsafeFunction(did) if did.is_some() => tcx.emit_spanned_lint( + CallToUnsafeFunction(Some(did)) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, UnsafeOpInUnsafeFnCallToUnsafeFunctionRequiresUnsafe { span, - function: &tcx.def_path_str(did.unwrap()), + function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), }, ), - CallToUnsafeFunction(..) => tcx.emit_spanned_lint( + CallToUnsafeFunction(None) => tcx.emit_spanned_lint( UNSAFE_OP_IN_UNSAFE_FN, hir_id, span, @@ -594,7 +597,7 @@ impl UnsafeOpKind { span, UnsafeOpInUnsafeFnCallToFunctionWithRequiresUnsafe { span, - function: &tcx.def_path_str(*did), + function: &with_no_trimmed_paths!(tcx.def_path_str(*did)), }, ), } @@ -607,24 +610,24 @@ impl UnsafeOpKind { unsafe_op_in_unsafe_fn_allowed: bool, ) { match self { - CallToUnsafeFunction(did) if did.is_some() && unsafe_op_in_unsafe_fn_allowed => { + CallToUnsafeFunction(Some(did)) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, - function: &tcx.def_path_str(did.unwrap()), + function: &tcx.def_path_str(*did), }); } - CallToUnsafeFunction(did) if did.is_some() => { + CallToUnsafeFunction(Some(did)) => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe { span, - function: &tcx.def_path_str(did.unwrap()), + function: &tcx.def_path_str(*did), }); } - CallToUnsafeFunction(..) if unsafe_op_in_unsafe_fn_allowed => { + CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span }, ); } - CallToUnsafeFunction(..) => { + CallToUnsafeFunction(None) => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span }); } UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => { diff --git a/src/test/ui/unsafe/auxiliary/issue-106126.rs b/src/test/ui/unsafe/auxiliary/issue-106126.rs new file mode 100644 index 000000000000..091a3edb756a --- /dev/null +++ b/src/test/ui/unsafe/auxiliary/issue-106126.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! foo { + () => { + unsafe fn __unsf() {} + unsafe fn __foo() { + __unsf(); + } + }; +} diff --git a/src/test/ui/unsafe/issue-106126-good-path-bug.rs b/src/test/ui/unsafe/issue-106126-good-path-bug.rs new file mode 100644 index 000000000000..93f478ee3580 --- /dev/null +++ b/src/test/ui/unsafe/issue-106126-good-path-bug.rs @@ -0,0 +1,12 @@ +// Regression test for #106126. +// check-pass +// aux-build:issue-106126.rs + +#![deny(unsafe_op_in_unsafe_fn)] + +#[macro_use] +extern crate issue_106126; + +foo!(); + +fn main() {} From 7770b06b06efc4abda75e608e67044a0a344771e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 13 Sep 2022 11:17:13 +0200 Subject: [PATCH 087/223] only specify --target by default for -Zgcc-ld=lld on wasm On macOS, it's not yet clear which cases of clang/OS/target/SDK version impact how to find ld/lld/rust-lld. The --target is not needed on our current targets with a vanilla config, but may be in some cases. Specifying it all the time breaks the 10.7+ targets on x64 macOS. We try to only specify it on macOS if the linker flavors are different, for possible cases of cross-compilation with `-Zgcc-ld=lld` but the expectation is that it should be passed manually when needed in these situations. --- compiler/rustc_codegen_ssa/src/back/link.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index edde1537b81e..36f7e5954bf2 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2822,11 +2822,30 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { // Implement the "linker flavor" part of -Zgcc-ld // by asking cc to use some kind of lld. cmd.arg("-fuse-ld=lld"); + if !flavor.is_gnu() { // Tell clang to use a non-default LLD flavor. // Gcc doesn't understand the target option, but we currently assume // that gcc is not used for Apple and Wasm targets (#97402). - cmd.arg(format!("--target={}", sess.target.llvm_target)); + // + // Note that we don't want to do that by default on macOS: e.g. passing a + // 10.7 target to LLVM works, but not to recent versions of clang/macOS, as + // shown in issue #101653 and the discussion in PR #101792. + // + // It could be required in some cases of cross-compiling with + // `-Zgcc-ld=lld`, but this is generally unspecified, and we don't know + // which specific versions of clang, macOS SDK, host and target OS + // combinations impact us here. + // + // So we do a simple first-approximation until we know more of what the + // Apple targets require (and which would be handled prior to hitting this + // `-Zgcc-ld=lld` codepath anyway), but the expectation is that until then + // this should be manually passed if needed. We specify the target when + // targeting a different linker flavor on macOS, and that's also always + // the case when targeting WASM. + if sess.target.linker_flavor != sess.host.linker_flavor { + cmd.arg(format!("--target={}", sess.target.llvm_target)); + } } } } From e9ca6636e108cb4380d38a45c5ebb1d485079210 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 2 Jan 2023 16:36:29 -0700 Subject: [PATCH 088/223] get latest x version from parsing cargo command --- Cargo.lock | 17 ++++++------ src/tools/tidy/Cargo.toml | 1 + src/tools/tidy/src/x_version.rs | 48 ++++++++++++++++++++++++++------- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8cafdc83d4f4..784aca237f04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4814,9 +4814,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -4833,9 +4833,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -4853,9 +4853,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "indexmap", "itoa", @@ -5133,9 +5133,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.102" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -5310,6 +5310,7 @@ dependencies = [ "miropt-test-tools", "regex", "semver", + "serde_json", "termcolor", "walkdir", ] diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 5f5ae3a65efa..a13ecbe955ac 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -12,6 +12,7 @@ lazy_static = "1" walkdir = "2" ignore = "0.4.18" semver = "1.0.14" +serde_json = "1.0.91" termcolor = "1.1.3" [[bin]] diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 868b3d925d3c..6cadc18fd3e9 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -1,4 +1,5 @@ -use semver::{BuildMetadata, Prerelease, Version}; +use semver::Version; +use serde_json::Value; use std::io::ErrorKind; use std::process::{Command, Stdio}; @@ -33,20 +34,47 @@ pub fn check(bad: &mut bool) { if output.status.success() { let version = String::from_utf8_lossy(&output.stdout); let version = Version::parse(version.trim_end()).unwrap(); - let expected = Version { - major: 0, - minor: 1, - patch: 0, - pre: Prerelease::new("").unwrap(), - build: BuildMetadata::EMPTY, - }; - if version < expected { + + if let Some(expected) = get_x_wrapper_version() { + if version < expected { + return tidy_error!( + bad, + "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + ); + } + } else { return tidy_error!( bad, - "Current version of x is {version}, but the latest version is {expected}\nConsider updating to the newer version of x by running `cargo install --path src/tools/x`" + "Unable to parse the latest version of `x` at `src/tools/x/Cargo.toml`" ); } } else { return tidy_error!(bad, "failed to check version of `x`: {}", output.status); } } + +// Parse latest version out of `x` Cargo.toml +fn get_x_wrapper_version() -> Option { + let cmd = Command::new("cargo") + .arg("metadata") + .args(["--no-deps", "--format-version", "1", "--manifest-path", "src/tools/x/Cargo.toml"]) + .stdout(Stdio::piped()) + .spawn(); + + let child = match cmd { + Ok(child) => child, + Err(e) => { + println!("failed to get version of `x`: {}", e); + return None; + } + }; + + let cargo_output = child.wait_with_output().unwrap(); + let cargo_output_str = + String::from_utf8(cargo_output.stdout).expect("Unable to parse `src/tools/x/Cargo.toml`"); + + let v: Value = serde_json::from_str(&cargo_output_str).unwrap(); + let vesrion_str = &v["packages"][0]["version"].as_str()?; + + Some(Version::parse(vesrion_str).unwrap()) +} From 3eabea9e2c16803ff5864a78be8ecaf1531005d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 Jan 2023 00:00:00 +0000 Subject: [PATCH 089/223] Remove duplicated elaborate box derefs pass The pass runs earlier as a part of `run_runtime_lowering_passes`. --- compiler/rustc_mir_transform/src/lib.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index ae79c2290f6d..806758f71dcd 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -524,11 +524,8 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { /// Returns the sequence of passes that do the initial cleanup of runtime MIR. fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let passes: &[&dyn MirPass<'tcx>] = &[ - &elaborate_box_derefs::ElaborateBoxDerefs, - &lower_intrinsics::LowerIntrinsics, - &simplify::SimplifyCfg::new("elaborate-drops"), - ]; + let passes: &[&dyn MirPass<'tcx>] = + &[&lower_intrinsics::LowerIntrinsics, &simplify::SimplifyCfg::new("elaborate-drops")]; pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup))); } From b2317a642d36e26e6cdf0624c38d461384f7b94e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 3 Jan 2023 01:09:08 +0000 Subject: [PATCH 090/223] has_overflow only if value is *not* within limit --- compiler/rustc_trait_selection/src/solve/overflow.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/solve/overflow.rs b/compiler/rustc_trait_selection/src/solve/overflow.rs index 8d73a83aec96..fdd6adb681be 100644 --- a/compiler/rustc_trait_selection/src/solve/overflow.rs +++ b/compiler/rustc_trait_selection/src/solve/overflow.rs @@ -36,7 +36,7 @@ impl OverflowData { #[inline] pub(super) fn has_overflow(&self, depth: usize) -> bool { - self.current_limit.value_within_limit(depth + self.additional_depth) + !self.current_limit.value_within_limit(depth + self.additional_depth) } /// Updating the current limit when hitting overflow. From 6c254ed6dca48ebbd83209493df0ffc1d2584f38 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Mon, 2 Jan 2023 17:26:16 -0800 Subject: [PATCH 091/223] rustdoc: allow popover child links to work No need to prevent default click behavior on a
, it will also disable all child click behavior. --- src/librustdoc/html/static/js/main.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 60e4e7492240..92baa68b5bef 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1040,9 +1040,6 @@ function loadCss(cssUrl) { help_button.appendChild(container); container.onblur = helpBlurHandler; - container.onclick = event => { - event.preventDefault(); - }; help_button.onblur = helpBlurHandler; help_button.children[0].onblur = helpBlurHandler; } From 376dd8a9b36eb4d0c192f3767562ca0bdab60ff9 Mon Sep 17 00:00:00 2001 From: DebugSteven Date: Mon, 2 Jan 2023 19:31:18 -0700 Subject: [PATCH 092/223] use cargo_metadata to get x version --- Cargo.lock | 1 - src/tools/tidy/Cargo.toml | 1 - src/tools/tidy/src/main.rs | 2 +- src/tools/tidy/src/x_version.rs | 36 +++++++++------------------------ 4 files changed, 11 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 784aca237f04..4cb64882cb7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5310,7 +5310,6 @@ dependencies = [ "miropt-test-tools", "regex", "semver", - "serde_json", "termcolor", "walkdir", ] diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index a13ecbe955ac..5f5ae3a65efa 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -12,7 +12,6 @@ lazy_static = "1" walkdir = "2" ignore = "0.4.18" semver = "1.0.14" -serde_json = "1.0.91" termcolor = "1.1.3" [[bin]] diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 56fcc561a3f8..7bb8ddc6949e 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -107,7 +107,7 @@ fn main() { check!(alphabetical, &compiler_path); check!(alphabetical, &library_path); - check!(x_version); + check!(x_version, &root_path, &cargo); let collected = { drain_handles(&mut handles); diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 6cadc18fd3e9..070a751b0518 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -1,9 +1,9 @@ use semver::Version; -use serde_json::Value; use std::io::ErrorKind; +use std::path::Path; use std::process::{Command, Stdio}; -pub fn check(bad: &mut bool) { +pub fn check(root: &Path, cargo: &Path, bad: &mut bool) { let result = Command::new("x").arg("--wrapper-version").stdout(Stdio::piped()).spawn(); // This runs the command inside a temporary directory. // This allows us to compare output of result to see if `--wrapper-version` is not a recognized argument to x. @@ -35,7 +35,7 @@ pub fn check(bad: &mut bool) { let version = String::from_utf8_lossy(&output.stdout); let version = Version::parse(version.trim_end()).unwrap(); - if let Some(expected) = get_x_wrapper_version() { + if let Some(expected) = get_x_wrapper_version(root, cargo) { if version < expected { return tidy_error!( bad, @@ -54,27 +54,11 @@ pub fn check(bad: &mut bool) { } // Parse latest version out of `x` Cargo.toml -fn get_x_wrapper_version() -> Option { - let cmd = Command::new("cargo") - .arg("metadata") - .args(["--no-deps", "--format-version", "1", "--manifest-path", "src/tools/x/Cargo.toml"]) - .stdout(Stdio::piped()) - .spawn(); - - let child = match cmd { - Ok(child) => child, - Err(e) => { - println!("failed to get version of `x`: {}", e); - return None; - } - }; - - let cargo_output = child.wait_with_output().unwrap(); - let cargo_output_str = - String::from_utf8(cargo_output.stdout).expect("Unable to parse `src/tools/x/Cargo.toml`"); - - let v: Value = serde_json::from_str(&cargo_output_str).unwrap(); - let vesrion_str = &v["packages"][0]["version"].as_str()?; - - Some(Version::parse(vesrion_str).unwrap()) +fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option { + let mut cmd = cargo_metadata::MetadataCommand::new(); + cmd.cargo_path(cargo) + .manifest_path(root.join("src/tools/x/Cargo.toml")) + .features(cargo_metadata::CargoOpt::AllFeatures); + let mut metadata = t!(cmd.exec()); + metadata.packages.pop().map(|x| x.version) } From 6f1d9ba581dbf1282825e87424021d8c4cb7ba54 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 3 Jan 2023 03:39:41 +0000 Subject: [PATCH 093/223] Allow passing a specific date to `bump-stage0` This allows regenerating `src/stage0.json` on changes to the tool, without needing to hard-code the date in the source. --- src/bootstrap/run.rs | 1 + src/tools/bump-stage0/src/main.rs | 27 ++++++++++++++++----------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 05de51f8cc57..e0280854541a 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -105,6 +105,7 @@ impl Step for BumpStage0 { fn run(self, builder: &Builder<'_>) -> Self::Output { let mut cmd = builder.tool_cmd(Tool::BumpStage0); + cmd.args(builder.config.cmd.args()); builder.run(&mut cmd); } } diff --git a/src/tools/bump-stage0/src/main.rs b/src/tools/bump-stage0/src/main.rs index aa346daf7e5f..530a80b1ed37 100644 --- a/src/tools/bump-stage0/src/main.rs +++ b/src/tools/bump-stage0/src/main.rs @@ -1,4 +1,4 @@ -use anyhow::Error; +use anyhow::{Context, Error}; use curl::easy::Easy; use indexmap::IndexMap; use std::collections::HashMap; @@ -13,12 +13,13 @@ struct Tool { comments: Vec, channel: Channel, + date: Option, version: [u16; 3], checksums: IndexMap, } impl Tool { - fn new() -> Result { + fn new(date: Option) -> Result { let channel = match std::fs::read_to_string("src/ci/channel")?.trim() { "stable" => Channel::Stable, "beta" => Channel::Beta, @@ -40,6 +41,7 @@ impl Tool { Ok(Self { channel, version, + date, config: existing.config, comments: existing.comments, checksums: IndexMap::new(), @@ -84,7 +86,7 @@ impl Tool { Channel::Nightly => "beta".to_string(), }; - let manifest = fetch_manifest(&self.config, &channel)?; + let manifest = fetch_manifest(&self.config, &channel, self.date.as_deref())?; self.collect_checksums(&manifest, COMPILER_COMPONENTS)?; Ok(Stage0Toolchain { date: manifest.date, @@ -110,7 +112,7 @@ impl Tool { return Ok(None); } - let manifest = fetch_manifest(&self.config, "nightly")?; + let manifest = fetch_manifest(&self.config, "nightly", self.date.as_deref())?; self.collect_checksums(&manifest, RUSTFMT_COMPONENTS)?; Ok(Some(Stage0Toolchain { date: manifest.date, version: "nightly".into() })) } @@ -141,16 +143,19 @@ impl Tool { } fn main() -> Result<(), Error> { - let tool = Tool::new()?; + let tool = Tool::new(std::env::args().nth(1))?; tool.update_json()?; Ok(()) } -fn fetch_manifest(config: &Config, channel: &str) -> Result { - Ok(toml::from_slice(&http_get(&format!( - "{}/dist/channel-rust-{}.toml", - config.dist_server, channel - ))?)?) +fn fetch_manifest(config: &Config, channel: &str, date: Option<&str>) -> Result { + let url = if let Some(date) = date { + format!("{}/dist/{}/channel-rust-{}.toml", config.dist_server, date, channel) + } else { + format!("{}/dist/channel-rust-{}.toml", config.dist_server, channel) + }; + + Ok(toml::from_slice(&http_get(&url)?)?) } fn http_get(url: &str) -> Result, Error> { @@ -164,7 +169,7 @@ fn http_get(url: &str) -> Result, Error> { data.extend_from_slice(new_data); Ok(new_data.len()) })?; - transfer.perform()?; + transfer.perform().context(format!("failed to fetch {url}"))?; } Ok(data) } From 85f649fd27754cf54dff48131b87800a02edb948 Mon Sep 17 00:00:00 2001 From: J Haigh Date: Mon, 2 Jan 2023 20:49:18 -0700 Subject: [PATCH 094/223] no_deps Co-authored-by: Joshua Nelson --- src/tools/tidy/src/x_version.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs index 070a751b0518..5dc6a0588c32 100644 --- a/src/tools/tidy/src/x_version.rs +++ b/src/tools/tidy/src/x_version.rs @@ -58,6 +58,7 @@ fn get_x_wrapper_version(root: &Path, cargo: &Path) -> Option { let mut cmd = cargo_metadata::MetadataCommand::new(); cmd.cargo_path(cargo) .manifest_path(root.join("src/tools/x/Cargo.toml")) + .no_deps() .features(cargo_metadata::CargoOpt::AllFeatures); let mut metadata = t!(cmd.exec()); metadata.packages.pop().map(|x| x.version) From e808a69911c31609b67c1e94a940b398af324f34 Mon Sep 17 00:00:00 2001 From: Rageking8 Date: Tue, 3 Jan 2023 15:48:16 +0800 Subject: [PATCH 095/223] fix dupe word typos --- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/early.rs | 2 +- compiler/rustc_lint/src/late.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index cdb901b7f860..10d8db5393da 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1392,7 +1392,7 @@ declare_lint! { /// /// The attribute must be used in conjunction with the /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]` - /// annotation will function as as no-op. + /// annotation will function as a no-op. /// /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html UNGATED_ASYNC_FN_TRACK_CALLER, diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index 5f84d5c8b949..c18abaef8e25 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -29,7 +29,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -/// Implements the AST traversal for early lint passes. `T` provides the the +/// Implements the AST traversal for early lint passes. `T` provides the /// `check_*` methods. pub struct EarlyContextAndPass<'a, T: EarlyLintPass> { context: EarlyContext<'a>, diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index e2876938d705..b2a2656746ee 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -40,7 +40,7 @@ macro_rules! lint_callback { ($cx:expr, $f:ident, $($args:expr),*) => ({ $cx.pass.$f(&$cx.context, $($args),*); }) } -/// Implements the AST traversal for late lint passes. `T` provides the the +/// Implements the AST traversal for late lint passes. `T` provides the /// `check_*` methods. pub struct LateContextAndPass<'tcx, T: LateLintPass<'tcx>> { context: LateContext<'tcx>, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 310a01194eaf..7db470359672 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -410,7 +410,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { /// This method will create a new module and push it onto the "modules stack" then call /// `visit_mod_contents`. Once done, it'll remove it from the "modules stack" and instead - /// add into into the list of modules of the current module. + /// add into the list of modules of the current module. fn enter_mod(&mut self, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol) { self.modules.push(Module::new(name, id, m.spans.inner_span)); From 7680b164b00af55e7af64bdc8027b6deb4fb8233 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 2 Jan 2023 19:30:39 +0000 Subject: [PATCH 096/223] jsondoclint: Parse args with clap. --- Cargo.lock | 18 +++++++++++++++++- src/tools/jsondoclint/Cargo.toml | 1 + src/tools/jsondoclint/src/main.rs | 14 ++++++++++---- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f99e58e59b8e..0483d50fc2a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -597,7 +597,7 @@ checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", - "clap_derive", + "clap_derive 3.2.18", "clap_lex 0.2.2", "indexmap", "once_cell", @@ -614,7 +614,9 @@ checksum = "6bf8832993da70a4c6d13c581f4463c2bdda27b9bf1c5498dc4365543abe6d6f" dependencies = [ "atty", "bitflags", + "clap_derive 4.0.13", "clap_lex 0.3.0", + "once_cell", "strsim", "termcolor", ] @@ -641,6 +643,19 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_derive" +version = "4.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.2.2" @@ -2097,6 +2112,7 @@ name = "jsondoclint" version = "0.1.0" dependencies = [ "anyhow", + "clap 4.0.15", "fs-err", "rustdoc-json-types", "serde_json", diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 84a6c7f96c46..0dda3935ed87 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0.62" +clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } serde_json = "1.0.85" diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index fc54c421b4b2..91a7aeb063f0 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -1,6 +1,5 @@ -use std::env; - -use anyhow::{anyhow, bail, Result}; +use anyhow::{bail, Result}; +use clap::Parser; use fs_err as fs; use rustdoc_json_types::{Crate, Id, FORMAT_VERSION}; use serde_json::Value; @@ -21,8 +20,15 @@ enum ErrorKind { Custom(String), } +#[derive(Parser)] +struct Cli { + /// The path to the json file to be linted + path: String, +} + fn main() -> Result<()> { - let path = env::args().nth(1).ok_or_else(|| anyhow!("no path given"))?; + let Cli { path } = Cli::parse(); + let contents = fs::read_to_string(&path)?; let krate: Crate = serde_json::from_str(&contents)?; assert_eq!(krate.format_version, FORMAT_VERSION); From 855b7e8cf3963b9f187249f1f38b6bb2baa9c353 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 2 Jan 2023 19:40:00 +0000 Subject: [PATCH 097/223] jsondoclint: Add `--verbose` flag. Without verbose: 0:61941:36627 not in index or paths, but refered to at '$.index["0:62007"].inner.for.inner.id' and 12 more With verbose: 0:10808:27206 not in index or paths, but refered to at '$.index["0:10813"].inner.for.inner.id', '$.index["0:52495"].inner.for.inner.id', '$.index["a:0:2666:215-0:10808:27206"].inner.for.inner.id', '$.index["a:0:2680:223-0:10808:27206"].inner.for.inner.id', '$.index["a:0:2730:7845-0:10808:27206"].inner.for.inner.id', '$.index["a:0:7731:21706-0:10808:27206"].inner.for.inner.id', '$.index["a:0:7732:21705-0:10808:27206"].inner.for.inner.id' --- src/tools/jsondoclint/src/main.rs | 32 +++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index 91a7aeb063f0..89965dc24039 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -24,10 +24,14 @@ enum ErrorKind { struct Cli { /// The path to the json file to be linted path: String, + + /// Show verbose output + #[arg(long)] + verbose: bool, } fn main() -> Result<()> { - let Cli { path } = Cli::parse(); + let Cli { path, verbose } = Cli::parse(); let contents = fs::read_to_string(&path)?; let krate: Crate = serde_json::from_str(&contents)?; @@ -53,11 +57,27 @@ fn main() -> Result<()> { err.id.0, json_find::to_jsonpath(&sel) ), - [sel, ..] => eprintln!( - "{} not in index or paths, but refered to at '{}' and more", - err.id.0, - json_find::to_jsonpath(&sel) - ), + [sel, ..] => { + if verbose { + let sels = sels + .iter() + .map(json_find::to_jsonpath) + .map(|i| format!("'{i}'")) + .collect::>() + .join(", "); + eprintln!( + "{} not in index or paths, but refered to at {sels}", + err.id.0 + ); + } else { + eprintln!( + "{} not in index or paths, but refered to at '{}' and {} more", + err.id.0, + json_find::to_jsonpath(&sel), + sels.len() - 1, + ) + } + } } } ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg), From 95329080d317f01f22ddce1dec8be693ef4b29f4 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 2 Jan 2023 19:54:08 +0000 Subject: [PATCH 098/223] jsondoclint: Find selector for missing ID when error is created, not reported. This is needed for json output, but even without that, it increases performance massivly. On my machine, in reduces the time to check core.json from 40.190s to 11.333s. --- src/tools/jsondoclint/src/main.rs | 73 ++++++++++---------- src/tools/jsondoclint/src/validator.rs | 13 +++- src/tools/jsondoclint/src/validator/tests.rs | 20 +++++- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index 89965dc24039..266900ea3a22 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -16,7 +16,7 @@ struct Error { #[derive(Debug, PartialEq, Eq)] enum ErrorKind { - NotFound, + NotFound(Vec), Custom(String), } @@ -37,49 +37,48 @@ fn main() -> Result<()> { let krate: Crate = serde_json::from_str(&contents)?; assert_eq!(krate.format_version, FORMAT_VERSION); - let mut validator = validator::Validator::new(&krate); + let krate_json: Value = serde_json::from_str(&contents)?; + + let mut validator = validator::Validator::new(&krate, krate_json); validator.check_crate(); if !validator.errs.is_empty() { for err in validator.errs { match err.kind { - ErrorKind::NotFound => { - let krate_json: Value = serde_json::from_str(&contents)?; - - let sels = - json_find::find_selector(&krate_json, &Value::String(err.id.0.clone())); - match &sels[..] { - [] => unreachable!( - "id must be in crate, or it wouldn't be reported as not found" - ), - [sel] => eprintln!( - "{} not in index or paths, but refered to at '{}'", - err.id.0, - json_find::to_jsonpath(&sel) - ), - [sel, ..] => { - if verbose { - let sels = sels - .iter() - .map(json_find::to_jsonpath) - .map(|i| format!("'{i}'")) - .collect::>() - .join(", "); - eprintln!( - "{} not in index or paths, but refered to at {sels}", - err.id.0 - ); - } else { - eprintln!( - "{} not in index or paths, but refered to at '{}' and {} more", - err.id.0, - json_find::to_jsonpath(&sel), - sels.len() - 1, - ) - } + ErrorKind::NotFound(sels) => match &sels[..] { + [] => { + unreachable!( + "id {:?} must be in crate, or it wouldn't be reported as not found", + err.id + ) + } + [sel] => eprintln!( + "{} not in index or paths, but refered to at '{}'", + err.id.0, + json_find::to_jsonpath(&sel) + ), + [sel, ..] => { + if verbose { + let sels = sels + .iter() + .map(json_find::to_jsonpath) + .map(|i| format!("'{i}'")) + .collect::>() + .join(", "); + eprintln!( + "{} not in index or paths, but refered to at {sels}", + err.id.0 + ); + } else { + eprintln!( + "{} not in index or paths, but refered to at '{}' and {} more", + err.id.0, + json_find::to_jsonpath(&sel), + sels.len() - 1, + ) } } - } + }, ErrorKind::Custom(msg) => eprintln!("{}: {}", err.id.0, msg), } } diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 291d02d67bd6..f1b9c1acbaec 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -7,8 +7,9 @@ use rustdoc_json_types::{ Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, }; +use serde_json::Value; -use crate::{item_kind::Kind, Error, ErrorKind}; +use crate::{item_kind::Kind, json_find, Error, ErrorKind}; /// The Validator walks over the JSON tree, and ensures it is well formed. /// It is made of several parts. @@ -22,6 +23,7 @@ use crate::{item_kind::Kind, Error, ErrorKind}; pub struct Validator<'a> { pub(crate) errs: Vec, krate: &'a Crate, + krate_json: Value, /// Worklist of Ids to check. todo: HashSet<&'a Id>, /// Ids that have already been visited, so don't need to be checked again. @@ -39,9 +41,10 @@ enum PathKind { } impl<'a> Validator<'a> { - pub fn new(krate: &'a Crate) -> Self { + pub fn new(krate: &'a Crate, krate_json: Value) -> Self { Self { krate, + krate_json, errs: Vec::new(), seen_ids: HashSet::new(), todo: HashSet::new(), @@ -373,7 +376,11 @@ impl<'a> Validator<'a> { } else { if !self.missing_ids.contains(id) { self.missing_ids.insert(id); - self.fail(id, ErrorKind::NotFound) + + let sels = json_find::find_selector(&self.krate_json, &Value::String(id.0.clone())); + assert_ne!(sels.len(), 0); + + self.fail(id, ErrorKind::NotFound(sels)) } } } diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index c4aeee9c53b7..37b826153efb 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -2,11 +2,16 @@ use std::collections::HashMap; use rustdoc_json_types::{Crate, Item, Visibility}; +use crate::json_find::SelectorPart; + use super::*; #[track_caller] fn check(krate: &Crate, errs: &[Error]) { - let mut validator = Validator::new(krate); + let krate_string = serde_json::to_string(krate).unwrap(); + let krate_json = serde_json::from_str(&krate_string).unwrap(); + + let mut validator = Validator::new(krate, krate_json); validator.check_crate(); assert_eq!(errs, &validator.errs[..]); @@ -46,5 +51,16 @@ fn errors_on_missing_links() { format_version: rustdoc_json_types::FORMAT_VERSION, }; - check(&k, &[Error { kind: ErrorKind::NotFound, id: id("1") }]); + check( + &k, + &[Error { + kind: ErrorKind::NotFound(vec![vec![ + SelectorPart::Field("index".to_owned()), + SelectorPart::Field("0".to_owned()), + SelectorPart::Field("links".to_owned()), + SelectorPart::Field("Not Found".to_owned()), + ]]), + id: id("1"), + }], + ); } From 226ab7fd759d94e81d6831f869e41502a7f183c7 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Mon, 2 Jan 2023 20:15:45 +0000 Subject: [PATCH 099/223] jsondoclint: Add option to dump errors as json. The output looks like: { "errors": [ { "id": "2:2017:1833", "kind": { "NotFound": [ [ {"Field": "index"}, {"Field": "0:0:1571"}, {"Field": "links"}, {"Field": "pointer::read"} ] ] } } ], "path": "/home/nixon/dev/rust/rust/build/x86_64-unknown-linux-gnu/test/rustdoc-json/intra-doc-links/pointer_method/pointer_method.json" } --- Cargo.lock | 1 + src/tools/jsondoclint/Cargo.toml | 1 + src/tools/jsondoclint/src/json_find.rs | 3 ++- src/tools/jsondoclint/src/main.rs | 25 ++++++++++++++++++++++--- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0483d50fc2a6..bb438f288f2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2115,6 +2115,7 @@ dependencies = [ "clap 4.0.15", "fs-err", "rustdoc-json-types", + "serde", "serde_json", ] diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 0dda3935ed87..8990310a4f47 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -10,4 +10,5 @@ anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" diff --git a/src/tools/jsondoclint/src/json_find.rs b/src/tools/jsondoclint/src/json_find.rs index 70e7440f7308..a183c4068ce8 100644 --- a/src/tools/jsondoclint/src/json_find.rs +++ b/src/tools/jsondoclint/src/json_find.rs @@ -1,8 +1,9 @@ use std::fmt::Write; +use serde::Serialize; use serde_json::Value; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub enum SelectorPart { Field(String), Index(usize), diff --git a/src/tools/jsondoclint/src/main.rs b/src/tools/jsondoclint/src/main.rs index 266900ea3a22..05e938f4f7df 100644 --- a/src/tools/jsondoclint/src/main.rs +++ b/src/tools/jsondoclint/src/main.rs @@ -1,25 +1,34 @@ +use std::io::{BufWriter, Write}; + use anyhow::{bail, Result}; use clap::Parser; use fs_err as fs; use rustdoc_json_types::{Crate, Id, FORMAT_VERSION}; +use serde::Serialize; use serde_json::Value; pub(crate) mod item_kind; mod json_find; mod validator; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Serialize, Clone)] struct Error { kind: ErrorKind, id: Id, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Serialize, Clone)] enum ErrorKind { NotFound(Vec), Custom(String), } +#[derive(Debug, Serialize)] +struct JsonOutput { + path: String, + errors: Vec, +} + #[derive(Parser)] struct Cli { /// The path to the json file to be linted @@ -28,10 +37,13 @@ struct Cli { /// Show verbose output #[arg(long)] verbose: bool, + + #[arg(long)] + json_output: Option, } fn main() -> Result<()> { - let Cli { path, verbose } = Cli::parse(); + let Cli { path, verbose, json_output } = Cli::parse(); let contents = fs::read_to_string(&path)?; let krate: Crate = serde_json::from_str(&contents)?; @@ -42,6 +54,13 @@ fn main() -> Result<()> { let mut validator = validator::Validator::new(&krate, krate_json); validator.check_crate(); + if let Some(json_output) = json_output { + let output = JsonOutput { path: path.clone(), errors: validator.errs.clone() }; + let mut f = BufWriter::new(fs::File::create(json_output)?); + serde_json::to_writer(&mut f, &output)?; + f.flush()?; + } + if !validator.errs.is_empty() { for err in validator.errs { match err.kind { From f1f99c611a77b2ca4f9bde02c1ad77a57c12fcc7 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Sun, 1 Jan 2023 20:07:45 +0000 Subject: [PATCH 100/223] clean: Remove `ctor_kind` from `VariantStruct`. It's always `None`. --- src/librustdoc/clean/mod.rs | 2 -- src/librustdoc/clean/types.rs | 1 - src/librustdoc/html/render/print_item.rs | 11 +---------- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 07a9c48365f4..025a4379f45a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1960,7 +1960,6 @@ pub(crate) fn clean_variant_def<'tcx>(variant: &ty::VariantDef, cx: &mut DocCont variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), ), None => VariantKind::Struct(VariantStruct { - ctor_kind: None, fields: variant.fields.iter().map(|field| clean_middle_field(field, cx)).collect(), }), }; @@ -1985,7 +1984,6 @@ fn clean_variant_data<'tcx>( let kind = match variant { hir::VariantData::Struct(..) => VariantKind::Struct(VariantStruct { - ctor_kind: None, fields: variant.fields().iter().map(|x| clean_field(x, cx)).collect(), }), hir::VariantData::Tuple(..) => { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 77ec02426212..6d55a6794f58 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2111,7 +2111,6 @@ impl Union { /// only as a variant in an enum. #[derive(Clone, Debug)] pub(crate) struct VariantStruct { - pub(crate) ctor_kind: Option, pub(crate) fields: Vec, } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 40dfb0697506..c16d6477fc37 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1229,16 +1229,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: w.write_str(")"); } clean::VariantKind::Struct(ref s) => { - render_struct( - w, - v, - None, - s.ctor_kind, - &s.fields, - " ", - false, - cx, - ); + render_struct(w, v, None, None, &s.fields, " ", false, cx); } }, _ => unreachable!(), From 25c153149ead5aebf7626a1ff42a6e0a3c35108e Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Fri, 30 Dec 2022 11:11:33 +0100 Subject: [PATCH 101/223] Add `build_helper` crate to share code between tidy and bootstrap --- Cargo.lock | 5 ++++ Cargo.toml | 1 + src/bootstrap/Cargo.lock | 5 ++++ src/bootstrap/Cargo.toml | 1 + src/bootstrap/format.rs | 30 +---------------------- src/bootstrap/lib.rs | 3 ++- src/bootstrap/native.rs | 4 +++- src/bootstrap/util.rs | 29 ---------------------- src/tools/build_helper/Cargo.toml | 8 +++++++ src/tools/build_helper/src/ci.rs | 40 +++++++++++++++++++++++++++++++ src/tools/build_helper/src/git.rs | 30 +++++++++++++++++++++++ src/tools/build_helper/src/lib.rs | 2 ++ 12 files changed, 98 insertions(+), 60 deletions(-) create mode 100644 src/tools/build_helper/Cargo.toml create mode 100644 src/tools/build_helper/src/ci.rs create mode 100644 src/tools/build_helper/src/git.rs create mode 100644 src/tools/build_helper/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f99e58e59b8e..7a86a1012a76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -259,6 +259,10 @@ dependencies = [ "toml", ] +[[package]] +name = "build_helper" +version = "0.1.0" + [[package]] name = "bump-stage0" version = "0.1.0" @@ -5304,6 +5308,7 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ + "build_helper", "cargo_metadata 0.14.0", "ignore", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 1cec4a84480c..ce08d4edb567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "library/std", "library/test", "src/rustdoc-json-types", + "src/tools/build_helper", "src/tools/cargotest", "src/tools/clippy", "src/tools/clippy/clippy_dev", diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock index efe8ae3169fc..4a0ba5925773 100644 --- a/src/bootstrap/Cargo.lock +++ b/src/bootstrap/Cargo.lock @@ -36,6 +36,7 @@ dependencies = [ name = "bootstrap" version = "0.0.0" dependencies = [ + "build_helper", "cc", "cmake", "fd-lock", @@ -70,6 +71,10 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "build_helper" +version = "0.1.0" + [[package]] name = "cc" version = "1.0.73" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index fafe82a9c128..22ceeca941e9 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -30,6 +30,7 @@ path = "bin/sccache-plus-cl.rs" test = false [dependencies] +build_helper = { path = "../tools/build_helper" } cmake = "0.1.38" fd-lock = "3.0.8" filetime = "0.2" diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 84e461189596..cca45f4a634e 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -2,6 +2,7 @@ use crate::builder::Builder; use crate::util::{output, program_out_of_date, t}; +use build_helper::git::get_rust_lang_rust_remote; use ignore::WalkBuilder; use std::collections::VecDeque; use std::path::{Path, PathBuf}; @@ -95,35 +96,6 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Option> { ) } -/// Finds the remote for rust-lang/rust. -/// For example for these remotes it will return `upstream`. -/// ```text -/// origin https://github.com/Nilstrieb/rust.git (fetch) -/// origin https://github.com/Nilstrieb/rust.git (push) -/// upstream https://github.com/rust-lang/rust (fetch) -/// upstream https://github.com/rust-lang/rust (push) -/// ``` -fn get_rust_lang_rust_remote() -> Result { - let mut git = Command::new("git"); - git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]); - - let output = git.output().map_err(|err| format!("{err:?}"))?; - if !output.status.success() { - return Err("failed to execute git config command".to_owned()); - } - - let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?; - - let rust_lang_remote = stdout - .lines() - .find(|remote| remote.contains("rust-lang")) - .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; - - let remote_name = - rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; - Ok(remote_name.into()) -} - #[derive(serde::Deserialize)] struct RustfmtConfig { ignore: Vec, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5ea41d10bc81..d44b96cfb991 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -113,6 +113,7 @@ use std::path::{Path, PathBuf}; use std::process::Command; use std::str; +use build_helper::ci::CiEnv; use channel::GitInfo; use config::{DryRun, Target}; use filetime::FileTime; @@ -121,7 +122,7 @@ use once_cell::sync::OnceCell; use crate::builder::Kind; use crate::config::{LlvmLibunwind, TargetSelection}; use crate::util::{ - exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, CiEnv, + exe, libdir, mtime, output, run, run_suppressed, symlink_dir, try_run_suppressed, }; mod bolt; diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 4e503dfe864e..bdc81b07b8d5 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -24,6 +24,8 @@ use crate::util::get_clang_cl_resource_dir; use crate::util::{self, exe, output, t, up_to_date}; use crate::{CLang, GitRepo}; +use build_helper::ci::CiEnv; + #[derive(Clone)] pub struct LlvmResult { /// Path to llvm-config binary. @@ -217,7 +219,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool { return false; } - if crate::util::CiEnv::is_ci() { + if CiEnv::is_ci() { // We assume we have access to git, so it's okay to unconditionally pass // `true` here. let llvm_sha = detect_llvm_sha(config, true); diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 58220783228b..8ce9a9ce38cc 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -255,35 +255,6 @@ pub enum CiEnv { GitHubActions, } -impl CiEnv { - /// Obtains the current CI environment. - pub fn current() -> CiEnv { - if env::var("TF_BUILD").map_or(false, |e| e == "True") { - CiEnv::AzurePipelines - } else if env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") { - CiEnv::GitHubActions - } else { - CiEnv::None - } - } - - pub fn is_ci() -> bool { - Self::current() != CiEnv::None - } - - /// If in a CI environment, forces the command to run with colors. - pub fn force_coloring_in_ci(self, cmd: &mut Command) { - if self != CiEnv::None { - // Due to use of stamp/docker, the output stream of rustbuild is not - // a TTY in CI, so coloring is by-default turned off. - // The explicit `TERM=xterm` environment is needed for - // `--color always` to actually work. This env var was lost when - // compiling through the Makefile. Very strange. - cmd.env("TERM", "xterm").args(&["--color", "always"]); - } - } -} - pub fn forcing_clang_based_tests() -> bool { if let Some(var) = env::var_os("RUSTBUILD_FORCE_CLANG_BASED_TESTS") { match &var.to_string_lossy().to_lowercase()[..] { diff --git a/src/tools/build_helper/Cargo.toml b/src/tools/build_helper/Cargo.toml new file mode 100644 index 000000000000..99f6fea2ecf9 --- /dev/null +++ b/src/tools/build_helper/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "build_helper" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs new file mode 100644 index 000000000000..9f113c72b933 --- /dev/null +++ b/src/tools/build_helper/src/ci.rs @@ -0,0 +1,40 @@ +use std::process::Command; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum CiEnv { + /// Not a CI environment. + None, + /// The Azure Pipelines environment, for Linux (including Docker), Windows, and macOS builds. + AzurePipelines, + /// The GitHub Actions environment, for Linux (including Docker), Windows and macOS builds. + GitHubActions, +} + +impl CiEnv { + /// Obtains the current CI environment. + pub fn current() -> CiEnv { + if std::env::var("TF_BUILD").map_or(false, |e| e == "True") { + CiEnv::AzurePipelines + } else if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") { + CiEnv::GitHubActions + } else { + CiEnv::None + } + } + + pub fn is_ci() -> bool { + Self::current() != CiEnv::None + } + + /// If in a CI environment, forces the command to run with colors. + pub fn force_coloring_in_ci(self, cmd: &mut Command) { + if self != CiEnv::None { + // Due to use of stamp/docker, the output stream of rustbuild is not + // a TTY in CI, so coloring is by-default turned off. + // The explicit `TERM=xterm` environment is needed for + // `--color always` to actually work. This env var was lost when + // compiling through the Makefile. Very strange. + cmd.env("TERM", "xterm").args(&["--color", "always"]); + } + } +} diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs new file mode 100644 index 000000000000..e9638206e672 --- /dev/null +++ b/src/tools/build_helper/src/git.rs @@ -0,0 +1,30 @@ +use std::process::Command; + +/// Finds the remote for rust-lang/rust. +/// For example for these remotes it will return `upstream`. +/// ```text +/// origin https://github.com/Nilstrieb/rust.git (fetch) +/// origin https://github.com/Nilstrieb/rust.git (push) +/// upstream https://github.com/rust-lang/rust (fetch) +/// upstream https://github.com/rust-lang/rust (push) +/// ``` +pub fn get_rust_lang_rust_remote() -> Result { + let mut git = Command::new("git"); + git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]); + + let output = git.output().map_err(|err| format!("{err:?}"))?; + if !output.status.success() { + return Err("failed to execute git config command".to_owned()); + } + + let stdout = String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?; + + let rust_lang_remote = stdout + .lines() + .find(|remote| remote.contains("rust-lang")) + .ok_or_else(|| "rust-lang/rust remote not found".to_owned())?; + + let remote_name = + rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; + Ok(remote_name.into()) +} diff --git a/src/tools/build_helper/src/lib.rs b/src/tools/build_helper/src/lib.rs new file mode 100644 index 000000000000..d3d2323db853 --- /dev/null +++ b/src/tools/build_helper/src/lib.rs @@ -0,0 +1,2 @@ +pub mod ci; +pub mod git; From 4fe2bd567536719e556d7fc9a4b571042b7807f9 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 3 Jan 2023 10:23:55 -0700 Subject: [PATCH 102/223] rustdoc: remove legacy font-feature-settings CSS According to [caniuse], these vendor prefixes aren't needed in any supported web browsers as defined in [RFC 1985]. * The last version of Chrome that required a vendor prefix was version 47. The current version is 108. * Firefox 33 is the last version that required a vendor prefix. The [current Firefox ESR] is version 102. * The last version of Safari that required a vendor prefix was version 9.1. The current version is 16. * The last version of Safari/iOS that required a vendor prefix was version 9.3. The current version is 16. * Edge never required vendor prefixes. * UCAndroid never required vendor prefixes. [caniuse]: https://caniuse.com/?search=font-feature-settings [RFC 1985]: https://rust-lang.github.io/rfcs/1985-tiered-browser-support.html [current Firefox ESR]: https://wiki.mozilla.org/Releases --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index bc0458bcd28f..f4c9cea5935f 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -110,11 +110,7 @@ body { /* Then override it with `anywhere`, which is required to make non-Safari browsers break more aggressively when we want them to. */ overflow-wrap: anywhere; - - -webkit-font-feature-settings: "kern", "liga"; - -moz-font-feature-settings: "kern", "liga"; font-feature-settings: "kern", "liga"; - background-color: var(--main-background-color); color: var(--main-color); } From 59eee74ce8b2b056c44f8743fd1661e4858cc12b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Jan 2023 18:10:32 +0100 Subject: [PATCH 103/223] Fix link generation for local primitive types in rustdoc JSON output --- src/librustdoc/json/conversions.rs | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index d7184053c87a..4a81a9d2d61a 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -8,8 +8,9 @@ use std::convert::From; use std::fmt; use rustc_ast::ast; -use rustc_hir::{def::CtorKind, def_id::DefId}; +use rustc_hir::{def::CtorKind, def::DefKind, def_id::DefId}; use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::symbol::sym; use rustc_span::{Pos, Symbol}; use rustc_target::spec::abi::Abi as RustcAbi; @@ -217,13 +218,27 @@ pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Opt impl<'a> fmt::Display for DisplayDefId<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let name = match self.2 { + let DisplayDefId(def_id, tcx, name) = self; + let name = match name { Some(name) => format!(":{}", name.as_u32()), - None => self - .1 - .opt_item_name(self.0) - .map(|n| format!(":{}", n.as_u32())) - .unwrap_or_default(), + None => { + // We need this workaround because primitive types' DefId actually refers to + // their parent module, which isn't present in the output JSON items. So + // instead, we directly get the primitive symbol and convert it to u32 to + // generate the ID. + if matches!(tcx.def_kind(def_id), DefKind::Mod) && + let Some(prim) = tcx.get_attrs(*def_id, sym::doc) + .flat_map(|attr| attr.meta_item_list().unwrap_or_default()) + .filter(|attr| attr.has_name(sym::primitive)) + .find_map(|attr| attr.value_str()) { + format!(":{}", prim.as_u32()) + } else { + tcx + .opt_item_name(*def_id) + .map(|n| format!(":{}", n.as_u32())) + .unwrap_or_default() + } + } }; write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name) } From f69fee4fea59fb84582a021d929fd6ecee37db8a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Jan 2023 18:29:40 +0100 Subject: [PATCH 104/223] Add regression test for #104064 --- .../primitives/local_primitive.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/rustdoc-json/primitives/local_primitive.rs diff --git a/src/test/rustdoc-json/primitives/local_primitive.rs b/src/test/rustdoc-json/primitives/local_primitive.rs new file mode 100644 index 000000000000..f27e6a2adeca --- /dev/null +++ b/src/test/rustdoc-json/primitives/local_primitive.rs @@ -0,0 +1,21 @@ +// Regression test for . + +#![feature(no_core)] +#![feature(rustc_attrs)] +#![feature(rustdoc_internals)] +#![no_core] +#![rustc_coherence_is_core] + +//! Link to [i32][prim@i32] [i64][prim@i64] + +#[doc(primitive = "i32")] +mod prim_i32 {} + +// @set local_i32 = "$.index[*][?(@.name=='i32')].id" + +// @has "$.index[*][?(@.name=='local_primitive')]" +// @ismany "$.index[*][?(@.name=='local_primitive')].inner.items[*]" $local_i32 +// @is "$.index[*][?(@.name=='local_primitive')].links['prim@i32']" $local_i32 + +// Let's ensure the `prim_i32` module isn't present in the output JSON: +// @!has "$.index[*][?(@.name=='prim_i32')]" From 9914a8924e651bd013d86ae6254a2283b7afc583 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 3 Jan 2023 09:47:03 -0800 Subject: [PATCH 105/223] Add cuviper to the review rotation for libs --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index 0da9fcddad8d..58108dac496b 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -479,6 +479,7 @@ compiler = [ "compiler-team-contributors", ] libs = [ + "@cuviper", "@joshtriplett", "@Mark-Simulacrum", "@m-ou-se", From 3534e0a393b447791fffaa84a97114dd3c761890 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 3 Jan 2023 04:13:19 +0000 Subject: [PATCH 106/223] Fix a few clippy lints in libtest - Remove unnecessary references and dereferences - Use `.contains` instead of `a <= x && x <= b` - Use `mem::take` instead of `mem::replace` where possible --- library/test/src/console.rs | 6 +++--- library/test/src/formatters/json.rs | 18 +++++++++--------- library/test/src/formatters/junit.rs | 16 ++++++++-------- library/test/src/formatters/pretty.rs | 16 ++++++++-------- library/test/src/formatters/terse.rs | 20 ++++++++++---------- library/test/src/lib.rs | 2 +- library/test/src/term/terminfo/mod.rs | 6 +++--- library/test/src/term/terminfo/parm.rs | 8 ++++---- library/test/src/term/terminfo/searcher.rs | 4 ++-- library/test/src/test_result.rs | 4 ++-- library/test/src/types.rs | 2 +- 11 files changed, 51 insertions(+), 51 deletions(-) diff --git a/library/test/src/console.rs b/library/test/src/console.rs index a3c39f71f08b..24cbe035f2fa 100644 --- a/library/test/src/console.rs +++ b/library/test/src/console.rs @@ -147,7 +147,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res let mut ntest = 0; let mut nbench = 0; - for test in filter_tests(&opts, tests).into_iter() { + for test in filter_tests(opts, tests).into_iter() { use crate::TestFn::*; let TestDescAndFn { desc: TestDesc { name, .. }, testfn } = test; @@ -244,7 +244,7 @@ fn on_test_event( let stdout = &completed_test.stdout; st.write_log_result(test, result, exec_time.as_ref())?; - out.write_result(test, result, exec_time.as_ref(), &*stdout, st)?; + out.write_result(test, result, exec_time.as_ref(), stdout, st)?; handle_test_result(st, completed_test); } } @@ -262,7 +262,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu let max_name_len = tests .iter() - .max_by_key(|t| len_if_padded(*t)) + .max_by_key(|t| len_if_padded(t)) .map(|t| t.desc.name.as_slice().len()) .unwrap_or(0); diff --git a/library/test/src/formatters/json.rs b/library/test/src/formatters/json.rs index 5526aadb67ff..95d2faf25060 100644 --- a/library/test/src/formatters/json.rs +++ b/library/test/src/formatters/json.rs @@ -40,20 +40,20 @@ impl JsonFormatter { extra: Option<&str>, ) -> io::Result<()> { // A doc test's name includes a filename which must be escaped for correct json. - self.write_message(&*format!( + self.write_message(&format!( r#"{{ "type": "{}", "name": "{}", "event": "{}""#, ty, EscapedString(name), evt ))?; if let Some(exec_time) = exec_time { - self.write_message(&*format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?; + self.write_message(&format!(r#", "exec_time": {}"#, exec_time.0.as_secs_f64()))?; } if let Some(stdout) = stdout { - self.write_message(&*format!(r#", "stdout": "{}""#, EscapedString(stdout)))?; + self.write_message(&format!(r#", "stdout": "{}""#, EscapedString(stdout)))?; } if let Some(extra) = extra { - self.write_message(&*format!(r#", {extra}"#))?; + self.write_message(&format!(r#", {extra}"#))?; } self.writeln_message(" }") } @@ -66,13 +66,13 @@ impl OutputFormatter for JsonFormatter { } else { String::new() }; - self.writeln_message(&*format!( + self.writeln_message(&format!( r#"{{ "type": "suite", "event": "started", "test_count": {test_count}{shuffle_seed_json} }}"# )) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { - self.writeln_message(&*format!( + self.writeln_message(&format!( r#"{{ "type": "test", "event": "started", "name": "{}" }}"#, EscapedString(desc.name.as_slice()) )) @@ -151,20 +151,20 @@ impl OutputFormatter for JsonFormatter { mbps ); - self.writeln_message(&*line) + self.writeln_message(&line) } } } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { - self.writeln_message(&*format!( + self.writeln_message(&format!( r#"{{ "type": "test", "event": "timeout", "name": "{}" }}"#, EscapedString(desc.name.as_slice()) )) } fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { - self.write_message(&*format!( + self.write_message(&format!( "{{ \"type\": \"suite\", \ \"event\": \"{}\", \ \"passed\": {}, \ diff --git a/library/test/src/formatters/junit.rs b/library/test/src/formatters/junit.rs index e6fb4f5707b3..7a40ce33cb74 100644 --- a/library/test/src/formatters/junit.rs +++ b/library/test/src/formatters/junit.rs @@ -64,7 +64,7 @@ impl OutputFormatter for JunitFormatter { fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { self.write_message("")?; - self.write_message(&*format!( + self.write_message(&format!( " OutputFormatter for JunitFormatter { >", state.failed, state.total, state.ignored ))?; - for (desc, result, duration) in std::mem::replace(&mut self.results, Vec::new()) { + for (desc, result, duration) in std::mem::take(&mut self.results) { let (class_name, test_name) = parse_class_name(&desc); match result { TestResult::TrIgnored => { /* no-op */ } TestResult::TrFailed => { - self.write_message(&*format!( + self.write_message(&format!( "", class_name, @@ -90,19 +90,19 @@ impl OutputFormatter for JunitFormatter { } TestResult::TrFailedMsg(ref m) => { - self.write_message(&*format!( + self.write_message(&format!( "", class_name, test_name, duration.as_secs_f64() ))?; - self.write_message(&*format!(""))?; + self.write_message(&format!(""))?; self.write_message("")?; } TestResult::TrTimedFail => { - self.write_message(&*format!( + self.write_message(&format!( "", class_name, @@ -114,7 +114,7 @@ impl OutputFormatter for JunitFormatter { } TestResult::TrBench(ref b) => { - self.write_message(&*format!( + self.write_message(&format!( "", class_name, test_name, b.ns_iter_summ.sum @@ -122,7 +122,7 @@ impl OutputFormatter for JunitFormatter { } TestResult::TrOk => { - self.write_message(&*format!( + self.write_message(&format!( "", class_name, diff --git a/library/test/src/formatters/pretty.rs b/library/test/src/formatters/pretty.rs index 0299c8b54335..247778e515f0 100644 --- a/library/test/src/formatters/pretty.rs +++ b/library/test/src/formatters/pretty.rs @@ -134,7 +134,7 @@ impl PrettyFormatter { let mut results = Vec::new(); let mut stdouts = String::new(); - for &(ref f, ref stdout) in inputs { + for (f, stdout) in inputs { results.push(f.name.to_string()); if !stdout.is_empty() { stdouts.push_str(&format!("---- {} stdout ----\n", f.name)); @@ -171,9 +171,9 @@ impl PrettyFormatter { fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> { let name = desc.padded_name(self.max_name_len, desc.name.padding()); if let Some(test_mode) = desc.test_mode() { - self.write_plain(&format!("test {name} - {test_mode} ... "))?; + self.write_plain(format!("test {name} - {test_mode} ... "))?; } else { - self.write_plain(&format!("test {name} ... "))?; + self.write_plain(format!("test {name} ... "))?; } Ok(()) @@ -188,7 +188,7 @@ impl OutputFormatter for PrettyFormatter { } else { String::new() }; - self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n")) + self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n")) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { @@ -221,7 +221,7 @@ impl OutputFormatter for PrettyFormatter { TestResult::TrIgnored => self.write_ignored(desc.ignore_message)?, TestResult::TrBench(ref bs) => { self.write_bench()?; - self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?; + self.write_plain(format!(": {}", fmt_bench_samples(bs)))?; } TestResult::TrTimedFail => self.write_time_failed()?, } @@ -231,7 +231,7 @@ impl OutputFormatter for PrettyFormatter { } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_plain(&format!( + self.write_plain(format!( "test {} has been running for over {} seconds\n", desc.name, time::TEST_WARN_TIMEOUT_S @@ -267,11 +267,11 @@ impl OutputFormatter for PrettyFormatter { state.passed, state.failed, state.ignored, state.measured, state.filtered_out ); - self.write_plain(&s)?; + self.write_plain(s)?; if let Some(ref exec_time) = state.exec_time { let time_str = format!("; finished in {exec_time}"); - self.write_plain(&time_str)?; + self.write_plain(time_str)?; } self.write_plain("\n\n")?; diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 5dace8baef7f..0837ab169051 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -70,7 +70,7 @@ impl TerseFormatter { // screen when dealing with line-buffered output (e.g., piping to // `stamp` in the rust CI). let out = format!(" {}/{}\n", self.test_count + 1, self.total_test_count); - self.write_plain(&out)?; + self.write_plain(out)?; } self.test_count += 1; @@ -106,7 +106,7 @@ impl TerseFormatter { self.write_plain("\nsuccesses:\n")?; let mut successes = Vec::new(); let mut stdouts = String::new(); - for &(ref f, ref stdout) in &state.not_failures { + for (f, stdout) in &state.not_failures { successes.push(f.name.to_string()); if !stdout.is_empty() { stdouts.push_str(&format!("---- {} stdout ----\n", f.name)); @@ -132,7 +132,7 @@ impl TerseFormatter { self.write_plain("\nfailures:\n")?; let mut failures = Vec::new(); let mut fail_out = String::new(); - for &(ref f, ref stdout) in &state.failures { + for (f, stdout) in &state.failures { failures.push(f.name.to_string()); if !stdout.is_empty() { fail_out.push_str(&format!("---- {} stdout ----\n", f.name)); @@ -157,9 +157,9 @@ impl TerseFormatter { fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> { let name = desc.padded_name(self.max_name_len, desc.name.padding()); if let Some(test_mode) = desc.test_mode() { - self.write_plain(&format!("test {name} - {test_mode} ... "))?; + self.write_plain(format!("test {name} - {test_mode} ... "))?; } else { - self.write_plain(&format!("test {name} ... "))?; + self.write_plain(format!("test {name} ... "))?; } Ok(()) @@ -175,7 +175,7 @@ impl OutputFormatter for TerseFormatter { } else { String::new() }; - self.write_plain(&format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n")) + self.write_plain(format!("\nrunning {test_count} {noun}{shuffle_seed_msg}\n")) } fn write_test_start(&mut self, desc: &TestDesc) -> io::Result<()> { @@ -209,13 +209,13 @@ impl OutputFormatter for TerseFormatter { self.write_test_name(desc)?; } self.write_bench()?; - self.write_plain(&format!(": {}\n", fmt_bench_samples(bs))) + self.write_plain(format!(": {}\n", fmt_bench_samples(bs))) } } } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { - self.write_plain(&format!( + self.write_plain(format!( "test {} has been running for over {} seconds\n", desc.name, time::TEST_WARN_TIMEOUT_S @@ -245,11 +245,11 @@ impl OutputFormatter for TerseFormatter { state.passed, state.failed, state.ignored, state.measured, state.filtered_out ); - self.write_plain(&s)?; + self.write_plain(s)?; if let Some(ref exec_time) = state.exec_time { let time_str = format!("; finished in {exec_time}"); - self.write_plain(&time_str)?; + self.write_plain(time_str)?; } self.write_plain("\n\n")?; diff --git a/library/test/src/lib.rs b/library/test/src/lib.rs index f6a41bbb88c8..30dc4ff85531 100644 --- a/library/test/src/lib.rs +++ b/library/test/src/lib.rs @@ -789,7 +789,7 @@ fn run_test_in_spawned_subprocess( } }); let record_result2 = record_result.clone(); - panic::set_hook(Box::new(move |info| record_result2(Some(&info)))); + panic::set_hook(Box::new(move |info| record_result2(Some(info)))); if let Err(message) = testfn() { panic!("{}", message); } diff --git a/library/test/src/term/terminfo/mod.rs b/library/test/src/term/terminfo/mod.rs index 355859019714..67ba89410cd9 100644 --- a/library/test/src/term/terminfo/mod.rs +++ b/library/test/src/term/terminfo/mod.rs @@ -149,7 +149,7 @@ impl Terminal for TerminfoTerminal { // are there any terminals that have color/attrs and not sgr0? // Try falling back to sgr, then op let cmd = match ["sgr0", "sgr", "op"].iter().find_map(|cap| self.ti.strings.get(*cap)) { - Some(op) => match expand(&op, &[], &mut Variables::new()) { + Some(op) => match expand(op, &[], &mut Variables::new()) { Ok(cmd) => cmd, Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)), }, @@ -180,12 +180,12 @@ impl TerminfoTerminal { } fn dim_if_necessary(&self, color: color::Color) -> color::Color { - if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color } + if color >= self.num_colors && (8..16).contains(&color) { color - 8 } else { color } } fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result { match self.ti.strings.get(cmd) { - Some(cmd) => match expand(&cmd, params, &mut Variables::new()) { + Some(cmd) => match expand(cmd, params, &mut Variables::new()) { Ok(s) => self.out.write_all(&s).and(Ok(true)), Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)), }, diff --git a/library/test/src/term/terminfo/parm.rs b/library/test/src/term/terminfo/parm.rs index 0756c8374aa6..2815f6cfc77f 100644 --- a/library/test/src/term/terminfo/parm.rs +++ b/library/test/src/term/terminfo/parm.rs @@ -282,14 +282,14 @@ pub(crate) fn expand( ); } SetVar => { - if cur >= 'A' && cur <= 'Z' { + if cur.is_ascii_uppercase() { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'A'; vars.sta_va[idx as usize] = arg; } else { return Err("stack is empty".to_string()); } - } else if cur >= 'a' && cur <= 'z' { + } else if cur.is_ascii_lowercase() { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'a'; vars.dyn_va[idx as usize] = arg; @@ -301,10 +301,10 @@ pub(crate) fn expand( } } GetVar => { - if cur >= 'A' && cur <= 'Z' { + if cur.is_ascii_uppercase() { let idx = (cur as u8) - b'A'; stack.push(vars.sta_va[idx as usize].clone()); - } else if cur >= 'a' && cur <= 'z' { + } else if cur.is_ascii_lowercase() { let idx = (cur as u8) - b'a'; stack.push(vars.dyn_va[idx as usize].clone()); } else { diff --git a/library/test/src/term/terminfo/searcher.rs b/library/test/src/term/terminfo/searcher.rs index 68e181a68957..87b91f34498a 100644 --- a/library/test/src/term/terminfo/searcher.rs +++ b/library/test/src/term/terminfo/searcher.rs @@ -22,7 +22,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option { if let Ok(dirs) = env::var("TERMINFO_DIRS") { for i in dirs.split(':') { - if i == "" { + if i.is_empty() { dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); } else { dirs_to_search.push(PathBuf::from(i)); @@ -49,7 +49,7 @@ pub(crate) fn get_dbpath_for_term(term: &str) -> Option { for mut p in dirs_to_search { if fs::metadata(&p).is_ok() { p.push(&first_char.to_string()); - p.push(&term); + p.push(term); if fs::metadata(&p).is_ok() { return Some(p); } diff --git a/library/test/src/test_result.rs b/library/test/src/test_result.rs index 7c5b0d6c0f72..1da238e3e8c0 100644 --- a/library/test/src/test_result.rs +++ b/library/test/src/test_result.rs @@ -33,7 +33,7 @@ pub fn calc_result<'a>( ) -> TestResult { let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TestResult::TrOk, - (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { + (&ShouldPanic::YesWithMessage(msg), Err(err)) => { let maybe_panic_str = err .downcast_ref::() .map(|e| &**e) @@ -52,7 +52,7 @@ pub fn calc_result<'a>( r#"expected panic with string value, found non-string value: `{:?}` expected substring: `{:?}`"#, - (**err).type_id(), + (*err).type_id(), msg )) } diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 888afff7921d..6f2e033095a3 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -47,7 +47,7 @@ impl TestName { match *self { StaticTestName(s) => s, DynTestName(ref s) => s, - AlignedTestName(ref s, _) => &*s, + AlignedTestName(ref s, _) => s, } } From 6eb205d591863f03e661f79ea3cb993f69eff844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 23 Nov 2022 18:20:57 +0000 Subject: [PATCH 107/223] bootstrap dist: ensure LLD's step --- src/bootstrap/dist.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 340aa78ebf9b..479bfeb8e856 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2067,6 +2067,12 @@ impl Step for RustDev { builder.ensure(crate::native::Llvm { target }); + // If the config has LLD enabled, ensure its step. We'll we want to package it, and use it + // in download-ci-llvm. + if builder.config.lld_enabled { + builder.ensure(crate::native::Lld { target }); + } + let src_bindir = builder.llvm_out(target).join("bin"); // If updating this list, you likely want to change // src/bootstrap/download-ci-llvm-stamp as well, otherwise local users From 835b58d61971890c3134f1d7a6a23d32f3ae7479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 23 Nov 2022 18:08:15 +0000 Subject: [PATCH 108/223] make the `native::LLD` step able to use an already built lld Makes the lld step avoid building it from source when possible: when dist has packaged it along the other LLVM binaries for the rust-dev component. --- src/bootstrap/native.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 4e503dfe864e..0f92c81e4d97 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -826,6 +826,20 @@ impl Step for Lld { let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target: self.target }); + // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path + // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin` + // subfolder. We check if that's the case, and if LLD's binary already exists there next to + // `llvm-config`: if so, we can use it instead of building LLVM/LLD from source. + let ci_llvm_bin = llvm_config.parent().unwrap(); + if ci_llvm_bin.is_dir() && ci_llvm_bin.file_name().unwrap() == "bin" { + let lld_path = ci_llvm_bin.join(exe("lld", target)); + if lld_path.exists() { + // The following steps copying `lld` as `rust-lld` to the sysroot, expect it in the + // `bin` subfolder of this step's out dir. + return ci_llvm_bin.parent().unwrap().to_path_buf(); + } + } + let out_dir = builder.lld_out(target); let done_stamp = out_dir.join("lld-finished-building"); if done_stamp.exists() { From 4e4658f0aafbf559a2c3e8674f10a06cadbfc737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 23 Nov 2022 18:12:58 +0000 Subject: [PATCH 109/223] slight cleanup --- src/bootstrap/native.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 0f92c81e4d97..48158d51e004 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -823,8 +823,7 @@ impl Step for Lld { } let target = self.target; - let LlvmResult { llvm_config, llvm_cmake_dir } = - builder.ensure(Llvm { target: self.target }); + let LlvmResult { llvm_config, llvm_cmake_dir } = builder.ensure(Llvm { target }); // The `dist` step packages LLD next to LLVM's binaries for download-ci-llvm. The root path // we usually expect here is `./build/$triple/ci-llvm/`, with the binaries in its `bin` From f635f9d4e4448bbccca28a93e42ca52043edeb41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 23 Nov 2022 18:16:37 +0000 Subject: [PATCH 110/223] turn a comment into an actual doc comment --- src/bootstrap/native.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 48158d51e004..781a738a8119 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -63,13 +63,13 @@ impl LdFlags { } } -// This returns whether we've already previously built LLVM. -// -// It's used to avoid busting caches during x.py check -- if we've already built -// LLVM, it's fine for us to not try to avoid doing so. -// -// This will return the llvm-config if it can get it (but it will not build it -// if not). +/// This returns whether we've already previously built LLVM. +/// +/// It's used to avoid busting caches during x.py check -- if we've already built +/// LLVM, it's fine for us to not try to avoid doing so. +/// +/// This will return the llvm-config if it can get it (but it will not build it +/// if not). pub fn prebuilt_llvm_config( builder: &Builder<'_>, target: TargetSelection, From c73a46c6bff445230a922e6b5e3018f87443bcbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Nov 2022 22:38:53 +0000 Subject: [PATCH 111/223] bump download-ci-llvm-stamp --- src/bootstrap/download-ci-llvm-stamp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index d19a1ae95cf1..94630e40f3c4 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/102790 +Last change is for: https://github.com/rust-lang/rust/pull/104748 From e0f5c6da1df52a64b80753bf33bae3176729ae52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 3 Jan 2023 20:21:49 +0000 Subject: [PATCH 112/223] ensure lld's step unconditionally for RustDev component --- src/bootstrap/dist.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 479bfeb8e856..68215790bed1 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -2067,11 +2067,8 @@ impl Step for RustDev { builder.ensure(crate::native::Llvm { target }); - // If the config has LLD enabled, ensure its step. We'll we want to package it, and use it - // in download-ci-llvm. - if builder.config.lld_enabled { - builder.ensure(crate::native::Lld { target }); - } + // We want to package `lld` to use it with `download-ci-llvm`. + builder.ensure(crate::native::Lld { target }); let src_bindir = builder.llvm_out(target).join("bin"); // If updating this list, you likely want to change From 077fae94a175408d8d7624af8a9fb96ce71bf3c3 Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 30 Dec 2022 05:09:09 +0000 Subject: [PATCH 113/223] Add note about wrapping in braces Previously it was not clear why this errored or if it was even supported, as there was no diagnostic that suggested wrapping it in braces. Thus, add a simple diagnostic that suggests wrapping enum variants in braces. --- .../rustc_hir_analysis/src/astconv/mod.rs | 29 ++++++++++------ .../assoc_const_eq_diagnostic.rs | 18 ++++++++++ .../assoc_const_eq_diagnostic.stderr | 33 +++++++++++++++++++ 3 files changed, 70 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/const-generics/assoc_const_eq_diagnostic.rs create mode 100644 src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index d7ab942665b3..686db67e36dc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1199,17 +1199,26 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (_, _) => { let got = if let Some(_) = term.ty() { "type" } else { "constant" }; let expected = def_kind.descr(assoc_item_def_id); - let reported = tcx - .sess - .struct_span_err( + let mut err = tcx.sess.struct_span_err( + binding.span, + &format!("expected {expected} bound, found {got}"), + ); + err.span_note( + tcx.def_span(assoc_item_def_id), + &format!("{expected} defined here"), + ); + + if let hir::def::DefKind::AssocConst = def_kind + && let Some(t) = term.ty() && (t.is_enum() || t.references_error()) + && tcx.features().associated_const_equality { + err.span_suggestion( binding.span, - &format!("expected {expected} bound, found {got}"), - ) - .span_note( - tcx.def_span(assoc_item_def_id), - &format!("{expected} defined here"), - ) - .emit(); + "if equating a const, try wrapping with braces", + format!("{} = {{ const }}", binding.item_name), + Applicability::HasPlaceholders, + ); + } + let reported = err.emit(); term = match def_kind { hir::def::DefKind::AssocTy => { tcx.ty_error_with_guaranteed(reported).into() diff --git a/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs b/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs new file mode 100644 index 000000000000..4d0aaf88e403 --- /dev/null +++ b/src/test/ui/const-generics/assoc_const_eq_diagnostic.rs @@ -0,0 +1,18 @@ +#![feature(associated_const_equality)] + +pub enum Mode { + Cool, +} + +pub trait Parse { + const MODE: Mode; +} + +pub trait CoolStuff: Parse {} +//~^ ERROR expected associated constant bound +//~| ERROR expected type + +fn no_help() -> Mode::Cool {} +//~^ ERROR expected type, found variant + +fn main() {} diff --git a/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr b/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr new file mode 100644 index 000000000000..ba727ee0ea30 --- /dev/null +++ b/src/test/ui/const-generics/assoc_const_eq_diagnostic.stderr @@ -0,0 +1,33 @@ +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:11:35 + | +LL | pub trait CoolStuff: Parse {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error[E0573]: expected type, found variant `Mode::Cool` + --> $DIR/assoc_const_eq_diagnostic.rs:15:17 + | +LL | fn no_help() -> Mode::Cool {} + | ^^^^^^^^^^ + | | + | not a type + | help: try using the variant's enum: `Mode` + +error: expected associated constant bound, found type + --> $DIR/assoc_const_eq_diagnostic.rs:11:28 + | +LL | pub trait CoolStuff: Parse {} + | ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }` + | +note: associated constant defined here + --> $DIR/assoc_const_eq_diagnostic.rs:8:5 + | +LL | const MODE: Mode; + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0573`. From a0390463fc27b627a86682722aaa11ff567212b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Dec 2022 23:56:46 +0000 Subject: [PATCH 114/223] Suggest more impl Trait on `-> _` --- compiler/rustc_hir_analysis/src/collect.rs | 141 ++++++++++++------- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/future/future.rs | 1 + src/test/ui/fn/issue-80179.rs | 5 +- src/test/ui/fn/issue-80179.stderr | 8 +- src/test/ui/fn/suggest-return-closure.rs | 31 ++++ src/test/ui/fn/suggest-return-closure.stderr | 30 ++++ src/test/ui/fn/suggest-return-future.rs | 23 +++ src/test/ui/fn/suggest-return-future.stderr | 21 +++ 9 files changed, 207 insertions(+), 54 deletions(-) create mode 100644 src/test/ui/fn/suggest-return-closure.rs create mode 100644 src/test/ui/fn/suggest-return-closure.stderr create mode 100644 src/test/ui/fn/suggest-return-future.rs create mode 100644 src/test/ui/fn/suggest-return-future.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1ff7429e415f..53a58df0916f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -17,6 +17,7 @@ use crate::astconv::AstConv; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; +use hir::def::DefKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; @@ -24,8 +25,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; -use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::ObligationCause; use rustc_middle::hir::nested_filter; use rustc_middle::ty::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; @@ -1195,12 +1196,11 @@ fn infer_return_ty_for_fn_sig<'tcx>( ty::ReErased => tcx.lifetimes.re_static, _ => r, }); - let fn_sig = ty::Binder::dummy(fn_sig); let mut visitor = HirPlaceholderCollector::default(); visitor.visit_ty(ty); let mut diag = bad_placeholder(tcx, visitor.0, "return type"); - let ret_ty = fn_sig.skip_binder().output(); + let ret_ty = fn_sig.output(); if ret_ty.is_suggestable(tcx, false) { diag.span_suggestion( ty.span, @@ -1223,6 +1223,13 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); } + } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, hir_id, def_id) { + diag.span_suggestion( + ty.span, + "replace with an appropriate return type", + sugg, + Applicability::MachineApplicable, + ); } else if ret_ty.is_closure() { // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds // to prevent the user from getting a papercut while trying to use the unique closure @@ -1232,17 +1239,10 @@ fn infer_return_ty_for_fn_sig<'tcx>( "for more information on `Fn` traits and closure types, see \ https://doc.rust-lang.org/book/ch13-01-closures.html", ); - } else if let Some(i_ty) = suggest_impl_iterator(tcx, ret_ty, ty.span, hir_id, def_id) { - diag.span_suggestion( - ty.span, - "replace with an appropriate return type", - format!("impl Iterator", i_ty), - Applicability::MachineApplicable, - ); } diag.emit(); - fn_sig + ty::Binder::dummy(fn_sig) } None => >::ty_of_fn( icx, @@ -1256,47 +1256,94 @@ fn infer_return_ty_for_fn_sig<'tcx>( } } -fn suggest_impl_iterator<'tcx>( +fn suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, hir_id: hir::HirId, def_id: LocalDefId, -) -> Option> { - let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) else { return None; }; - let Some(iterator_item) = tcx.get_diagnostic_item(sym::IteratorItem) else { return None; }; - if !tcx - .infer_ctxt() - .build() - .type_implements_trait(iter_trait, [ret_ty], tcx.param_env(def_id)) - .must_apply_modulo_regions() - { - return None; - } - let infcx = tcx.infer_ctxt().build(); - let ocx = ObligationCtxt::new_in_snapshot(&infcx); - // Find the type of `Iterator::Item`. - let origin = TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }; - let ty_var = infcx.next_ty_var(origin); - let projection = ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Projection( - ty::ProjectionPredicate { - projection_ty: tcx.mk_alias_ty(iterator_item, tcx.mk_substs([ret_ty.into()].iter())), - term: ty_var.into(), - }, - ))); - // Add `::Item = _` obligation. - ocx.register_obligation(crate::traits::Obligation::misc( - tcx, - span, - hir_id, - tcx.param_env(def_id), - projection, - )); - if ocx.select_where_possible().is_empty() - && let item_ty = infcx.resolve_vars_if_possible(ty_var) - && item_ty.is_suggestable(tcx, false) - { - return Some(item_ty); +) -> Option { + let format_as_assoc: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + _: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + assoc_item_def_id: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let assoc_name = tcx.item_name(assoc_item_def_id); + Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>")) + }; + let format_as_parenthesized: fn(_, _, _, _, _) -> _ = + |tcx: TyCtxt<'tcx>, + substs: ty::SubstsRef<'tcx>, + trait_def_id: DefId, + _: DefId, + item_ty: Ty<'tcx>| { + let trait_name = tcx.item_name(trait_def_id); + let args_tuple = substs.type_at(1); + let ty::Tuple(types) = *args_tuple.kind() else { return None; }; + if !types.is_suggestable(tcx, false) { + return None; + } + let maybe_ret = + if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") }; + Some(format!( + "impl {trait_name}({}){maybe_ret}", + types.iter().map(|ty| ty.to_string()).collect::>().join(", ") + )) + }; + + for (trait_def_id, assoc_item_def_id, formatter) in [ + ( + tcx.get_diagnostic_item(sym::Iterator), + tcx.get_diagnostic_item(sym::IteratorItem), + format_as_assoc, + ), + ( + tcx.lang_items().future_trait(), + tcx.get_diagnostic_item(sym::FutureOutput), + format_as_assoc, + ), + (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized), + ( + tcx.lang_items().fn_mut_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ( + tcx.lang_items().fn_once_trait(), + tcx.lang_items().fn_once_output(), + format_as_parenthesized, + ), + ] { + let Some(trait_def_id) = trait_def_id else { continue; }; + let Some(assoc_item_def_id) = assoc_item_def_id else { continue; }; + if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy { + continue; + } + let param_env = tcx.param_env(def_id); + let infcx = tcx.infer_ctxt().build(); + let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| { + if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) } + }); + if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions() + { + continue; + } + let ocx = ObligationCtxt::new_in_snapshot(&infcx); + let item_ty = ocx.normalize( + &ObligationCause::misc(span, hir_id), + param_env, + tcx.mk_projection(assoc_item_def_id, substs), + ); + // FIXME(compiler-errors): We may benefit from resolving regions here. + if ocx.select_where_possible().is_empty() + && let item_ty = infcx.resolve_vars_if_possible(item_ty) + && item_ty.is_suggestable(tcx, false) + && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty) + { + return Some(sugg); + } } None } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 85510fa2c660..5d5f8d6d6540 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -193,6 +193,7 @@ symbols! { FromIterator, FromResidual, Future, + FutureOutput, FxHashMap, FxHashSet, GlobalAlloc, diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs index f29d3e1e98b7..8c7111cb3ff0 100644 --- a/library/core/src/future/future.rs +++ b/library/core/src/future/future.rs @@ -37,6 +37,7 @@ use crate::task::{Context, Poll}; pub trait Future { /// The type of value produced on completion. #[stable(feature = "futures_api", since = "1.36.0")] + #[rustc_diagnostic_item = "FutureOutput"] type Output; /// Attempt to resolve the future to a final value, registering diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs index fcef6f1b60ec..bea8deadc898 100644 --- a/src/test/ui/fn/issue-80179.rs +++ b/src/test/ui/fn/issue-80179.rs @@ -18,9 +18,8 @@ fn returns_fn_ptr() -> _ { fn returns_closure() -> _ { //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] //~| NOTE not allowed in type signatures -//~| HELP consider using an `Fn`, `FnMut`, or `FnOnce` trait bound -//~| NOTE for more information on `Fn` traits and closure types, see -// https://doc.rust-lang.org/book/ch13-01-closures.html +//~| HELP replace with an appropriate return type +//~| SUGGESTION impl Fn() -> i32 || 0 } diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr index 2ca4ae982d96..dff8252b3715 100644 --- a/src/test/ui/fn/issue-80179.stderr +++ b/src/test/ui/fn/issue-80179.stderr @@ -11,10 +11,10 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures --> $DIR/issue-80179.rs:18:25 | LL | fn returns_closure() -> _ { - | ^ not allowed in type signatures - | - = help: consider using an `Fn`, `FnMut`, or `FnOnce` trait bound - = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` error: aborting due to 2 previous errors diff --git a/src/test/ui/fn/suggest-return-closure.rs b/src/test/ui/fn/suggest-return-closure.rs new file mode 100644 index 000000000000..1b9094cea38e --- /dev/null +++ b/src/test/ui/fn/suggest-return-closure.rs @@ -0,0 +1,31 @@ +fn fn_once() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnOnce() + let x = String::new(); + || { + drop(x); + } +} + +fn fn_mut() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl FnMut(char) + let x = String::new(); + |c| { + x.push(c); + } +} + +fn fun() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Fn() -> i32 + || 1i32 +} + +fn main() {} diff --git a/src/test/ui/fn/suggest-return-closure.stderr b/src/test/ui/fn/suggest-return-closure.stderr new file mode 100644 index 000000000000..f4b2c7f52740 --- /dev/null +++ b/src/test/ui/fn/suggest-return-closure.stderr @@ -0,0 +1,30 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:1:17 + | +LL | fn fn_once() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnOnce()` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:12:16 + | +LL | fn fn_mut() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl FnMut(char)` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-closure.rs:23:13 + | +LL | fn fun() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Fn() -> i32` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/fn/suggest-return-future.rs b/src/test/ui/fn/suggest-return-future.rs new file mode 100644 index 000000000000..750740d94261 --- /dev/null +++ b/src/test/ui/fn/suggest-return-future.rs @@ -0,0 +1,23 @@ +// edition: 2021 + +async fn a() -> i32 { + 0 +} + +fn foo() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + a() +} + +fn bar() -> _ { + //~^ ERROR the placeholder `_` is not allowed within types on item signatures for return types [E0121] + //~| NOTE not allowed in type signatures + //~| HELP replace with an appropriate return type + //~| SUGGESTION impl Future + async { a().await } +} + +fn main() {} diff --git a/src/test/ui/fn/suggest-return-future.stderr b/src/test/ui/fn/suggest-return-future.stderr new file mode 100644 index 000000000000..a4c8b5d8c4b5 --- /dev/null +++ b/src/test/ui/fn/suggest-return-future.stderr @@ -0,0 +1,21 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:7:13 + | +LL | fn foo() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types + --> $DIR/suggest-return-future.rs:15:13 + | +LL | fn bar() -> _ { + | ^ + | | + | not allowed in type signatures + | help: replace with an appropriate return type: `impl Future` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`. From 89086f7d36e3a692b48cae8a408057734f044567 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Jan 2023 00:26:53 +0000 Subject: [PATCH 115/223] Restore Fn trait note --- compiler/rustc_hir_analysis/src/collect.rs | 6 +++--- src/test/ui/fn/issue-80179.rs | 1 + src/test/ui/fn/issue-80179.stderr | 2 ++ src/test/ui/fn/suggest-return-closure.rs | 3 +++ src/test/ui/fn/suggest-return-closure.stderr | 10 ++++++++-- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 53a58df0916f..cf847047c906 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1231,10 +1231,10 @@ fn infer_return_ty_for_fn_sig<'tcx>( Applicability::MachineApplicable, ); } else if ret_ty.is_closure() { - // We're dealing with a closure, so we should suggest using `impl Fn` or trait bounds - // to prevent the user from getting a papercut while trying to use the unique closure - // syntax (e.g. `[closure@src/lib.rs:2:5: 2:9]`). diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound"); + } + // Also note how `Fn` traits work just in case! + if ret_ty.is_closure() { diag.note( "for more information on `Fn` traits and closure types, see \ https://doc.rust-lang.org/book/ch13-01-closures.html", diff --git a/src/test/ui/fn/issue-80179.rs b/src/test/ui/fn/issue-80179.rs index bea8deadc898..35e39bebb29a 100644 --- a/src/test/ui/fn/issue-80179.rs +++ b/src/test/ui/fn/issue-80179.rs @@ -20,6 +20,7 @@ fn returns_closure() -> _ { //~| NOTE not allowed in type signatures //~| HELP replace with an appropriate return type //~| SUGGESTION impl Fn() -> i32 +//~| NOTE for more information on `Fn` traits and closure types || 0 } diff --git a/src/test/ui/fn/issue-80179.stderr b/src/test/ui/fn/issue-80179.stderr index dff8252b3715..f5d6c44db751 100644 --- a/src/test/ui/fn/issue-80179.stderr +++ b/src/test/ui/fn/issue-80179.stderr @@ -15,6 +15,8 @@ LL | fn returns_closure() -> _ { | | | not allowed in type signatures | help: replace with an appropriate return type: `impl Fn() -> i32` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error: aborting due to 2 previous errors diff --git a/src/test/ui/fn/suggest-return-closure.rs b/src/test/ui/fn/suggest-return-closure.rs index 1b9094cea38e..33daa1ea0b40 100644 --- a/src/test/ui/fn/suggest-return-closure.rs +++ b/src/test/ui/fn/suggest-return-closure.rs @@ -3,6 +3,7 @@ fn fn_once() -> _ { //~| NOTE not allowed in type signatures //~| HELP replace with an appropriate return type //~| SUGGESTION impl FnOnce() + //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); || { drop(x); @@ -14,6 +15,7 @@ fn fn_mut() -> _ { //~| NOTE not allowed in type signatures //~| HELP replace with an appropriate return type //~| SUGGESTION impl FnMut(char) + //~| NOTE for more information on `Fn` traits and closure types let x = String::new(); |c| { x.push(c); @@ -25,6 +27,7 @@ fn fun() -> _ { //~| NOTE not allowed in type signatures //~| HELP replace with an appropriate return type //~| SUGGESTION impl Fn() -> i32 + //~| NOTE for more information on `Fn` traits and closure types || 1i32 } diff --git a/src/test/ui/fn/suggest-return-closure.stderr b/src/test/ui/fn/suggest-return-closure.stderr index f4b2c7f52740..341044469ea3 100644 --- a/src/test/ui/fn/suggest-return-closure.stderr +++ b/src/test/ui/fn/suggest-return-closure.stderr @@ -6,24 +6,30 @@ LL | fn fn_once() -> _ { | | | not allowed in type signatures | help: replace with an appropriate return type: `impl FnOnce()` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:12:16 + --> $DIR/suggest-return-closure.rs:13:16 | LL | fn fn_mut() -> _ { | ^ | | | not allowed in type signatures | help: replace with an appropriate return type: `impl FnMut(char)` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types - --> $DIR/suggest-return-closure.rs:23:13 + --> $DIR/suggest-return-closure.rs:25:13 | LL | fn fun() -> _ { | ^ | | | not allowed in type signatures | help: replace with an appropriate return type: `impl Fn() -> i32` + | + = note: for more information on `Fn` traits and closure types, see https://doc.rust-lang.org/book/ch13-01-closures.html error: aborting due to 3 previous errors From a313ef05a78330ac342cddf819214cb6414164e2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 3 Jan 2023 07:31:04 +0000 Subject: [PATCH 116/223] rename get_parent_node to parent_id --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- compiler/rustc_hir/src/hir.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 4 +-- .../src/collect/generics_of.rs | 4 +-- .../src/collect/lifetimes.rs | 2 +- .../src/collect/predicates_of.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 8 +++--- compiler/rustc_hir_typeck/src/_match.rs | 4 +-- compiler/rustc_hir_typeck/src/callee.rs | 6 ++--- compiler/rustc_hir_typeck/src/coercion.rs | 6 ++--- compiler/rustc_hir_typeck/src/demand.rs | 24 ++++++++--------- compiler/rustc_hir_typeck/src/expr.rs | 8 +++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 4 +-- compiler/rustc_hir_typeck/src/lib.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 19 +++++++------- compiler/rustc_hir_typeck/src/pat.rs | 4 +-- .../src/infer/error_reporting/suggest.rs | 6 ++--- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/internal.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 3 +-- compiler/rustc_lint/src/types.rs | 6 ++--- compiler/rustc_middle/src/hir/map/mod.rs | 26 +++++++++---------- compiler/rustc_middle/src/lint.rs | 2 +- compiler/rustc_middle/src/ty/error.rs | 2 +- .../src/thir/pattern/check_match.rs | 12 ++++----- compiler/rustc_privacy/src/lib.rs | 2 +- compiler/rustc_save_analysis/src/lib.rs | 2 +- .../error_reporting/on_unimplemented.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 20 +++++++------- compiler/rustc_ty_utils/src/ty.rs | 2 +- src/tools/clippy/clippy_lints/src/escape.rs | 6 ++--- .../clippy_lints/src/index_refutable_slice.rs | 4 +-- .../clippy_lints/src/loops/same_item_push.rs | 2 +- .../clippy_lints/src/manual_rem_euclid.rs | 2 +- .../src/matches/match_single_binding.rs | 6 ++--- .../src/mixed_read_write_in_expression.rs | 2 +- .../src/needless_pass_by_value.rs | 2 +- .../clippy/clippy_lints/src/non_copy_const.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- .../clippy_lints/src/unit_types/unit_arg.rs | 4 +-- .../clippy_lints/src/unnecessary_wraps.rs | 2 +- .../internal_lints/metadata_collector.rs | 2 +- .../internal_lints/unnecessary_def_path.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +-- 48 files changed, 119 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3c3cb8c6b9c2..6b663ea31470 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -394,7 +394,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } let typeck = self.infcx.tcx.typeck(self.mir_def_id()); - let hir_id = hir.get_parent_node(expr.hir_id); + let hir_id = hir.parent_id(expr.hir_id); if let Some(parent) = hir.find(hir_id) { let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 6f6d1b01bd42..c022fb55a16f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let hir = self.infcx.tcx.hir(); let closure_id = self.mir_hir_id(); let closure_span = self.infcx.tcx.def_span(self.mir_def_id()); - let fn_call_id = hir.get_parent_node(closure_id); + let fn_call_id = hir.parent_id(closure_id); let node = hir.get(fn_call_id); let def_id = hir.enclosing_body_owner(fn_call_id); let mut look_at_return = true; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 034f06bb889b..4f74dbe99e3d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3460,7 +3460,7 @@ impl<'hir> Node<'hir> { /// ```ignore (illustrative) /// ctor /// .ctor_hir_id() - /// .and_then(|ctor_id| tcx.hir().find(tcx.hir().get_parent_node(ctor_id))) + /// .and_then(|ctor_id| tcx.hir().find(tcx.hir().parent_id(ctor_id))) /// .and_then(|parent| parent.ident()) /// ``` pub fn ident(&self) -> Option { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index d7ab942665b3..93b91b3c9c62 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2936,7 +2936,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) = hir.get(fn_hir_id) else { return None }; let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) = - hir.get(hir.get_parent_node(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; + hir.get(hir.parent_id(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; let trait_ref = self.instantiate_mono_trait_ref( i.of_trait.as_ref()?, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 1ff7429e415f..fb732d7f9452 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -212,7 +212,7 @@ pub(crate) fn placeholder_type_error_diag<'tcx>( is_fn = true; // Check if parent is const or static - let parent_id = tcx.hir().get_parent_node(hir_ty.hir_id); + let parent_id = tcx.hir().parent_id(hir_ty.hir_id); let parent_node = tcx.hir().get(parent_id); is_const_or_static = matches!( @@ -1108,7 +1108,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { // Do not try to infer the return type for a impl method coming from a trait if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = - tcx.hir().get(tcx.hir().get_parent_node(hir_id)) + tcx.hir().get(tcx.hir().parent_id(hir_id)) && i.of_trait.is_some() { >::ty_of_fn( diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index cb4c35c0ce17..8ff96869b557 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -103,7 +103,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // `min_const_generics`. Some(parent_def_id.to_def_id()) } else { - let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); match parent_node { // HACK(eddyb) this provides the correct generics for repeat // expressions' count (i.e. `N` in `[x; N]`), and explicit @@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // provide junk type parameter defs for const blocks. if let Node::AnonConst(_) = node { - let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { params.push(ty::GenericParamDef { index: next_index(), diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index fb519d6731df..0a1188c16a8b 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -682,7 +682,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { }; let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB - let parent_id = self.tcx.hir().get_parent_node(hir_id); + let parent_id = self.tcx.hir().parent_id(hir_id); if !parent_id.is_owner() { struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 0943350e2d47..8412b7418b3a 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -270,7 +270,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // We create bi-directional Outlives predicates between the original // and the duplicated parameter, to ensure that they do not get out of sync. if let Node::Item(&Item { kind: ItemKind::OpaqueTy(..), .. }) = node { - let opaque_ty_id = tcx.hir().get_parent_node(hir_id); + let opaque_ty_id = tcx.hir().parent_id(hir_id); let opaque_ty_node = tcx.hir().get(opaque_ty_id); let Node::Ty(&Ty { kind: TyKind::OpaqueDef(_, lifetimes, _), .. }) = opaque_ty_node else { bug!("unexpected {opaque_ty_node:?}") diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 4bd55a548314..1c8acf6590de 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -28,7 +28,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< _ => return None, }; - let parent_node_id = tcx.hir().get_parent_node(hir_id); + let parent_node_id = tcx.hir().parent_id(hir_id); let parent_node = tcx.hir().get(parent_node_id); let (generics, arg_idx) = match parent_node { @@ -402,7 +402,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } Node::AnonConst(_) => { - let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) @@ -445,7 +445,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .. }, ) if let Node::TraitRef(trait_ref) = - tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + tcx.hir().get(tcx.hir().parent_id(binding_id)) && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { @@ -472,7 +472,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::TypeBinding( binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. }, ) if let Node::TraitRef(trait_ref) = - tcx.hir().get(tcx.hir().get_parent_node(binding_id)) + tcx.hir().get(tcx.hir().parent_id(binding_id)) && let Some((idx, _)) = gen_args.args.iter().enumerate().find(|(_, arg)| { if let GenericArg::Const(ct) = arg { diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index ab12cae4e2b0..7659b2d0a0b8 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -289,7 +289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn maybe_get_coercion_reason(&self, hir_id: hir::HirId, sp: Span) -> Option<(Span, String)> { let node = { - let rslt = self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(hir_id)); + let rslt = self.tcx.hir().parent_id(self.tcx.hir().parent_id(hir_id)); self.tcx.hir().get(rslt) }; if let hir::Node::Block(block) = node { @@ -297,7 +297,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let parent = self .tcx .hir() - .get(self.tcx.hir().get_parent_node(self.tcx.hir().get_parent_node(block.hir_id))); + .get(self.tcx.hir().parent_id(self.tcx.hir().parent_id(block.hir_id))); if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) = (&block.expr, parent) { diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 829913d278d0..2cb976f718c2 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -288,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { callee_span: Span, ) { let hir = self.tcx.hir(); - let parent_hir_id = hir.get_parent_node(hir_id); + let parent_hir_id = hir.parent_id(hir_id); let parent_node = hir.get(parent_hir_id); if let ( hir::Node::Expr(hir::Expr { @@ -303,7 +303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // Actually need to unwrap a few more layers of HIR to get to // the _real_ closure... - let async_closure = hir.get_parent_node(hir.get_parent_node(parent_hir_id)); + let async_closure = hir.parent_id(hir.parent_id(parent_hir_id)); if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }), .. @@ -336,7 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr: &'tcx hir::Expr<'tcx>, callee_expr: &'tcx hir::Expr<'tcx>, ) -> bool { - let hir_id = self.tcx.hir().get_parent_node(call_expr.hir_id); + let hir_id = self.tcx.hir().parent_id(call_expr.hir_id); let parent_node = self.tcx.hir().get(hir_id); if let ( hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Array(_), .. }), diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 3fb14e31ea11..9e91a3f90764 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1547,7 +1547,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { err.span_label(cause.span, "return type is not `()`"); } ObligationCauseCode::BlockTailExpression(blk_id) => { - let parent_id = fcx.tcx.hir().get_parent_node(blk_id); + let parent_id = fcx.tcx.hir().parent_id(blk_id); err = self.report_return_mismatched_types( cause, expected, @@ -1578,7 +1578,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { None, ); if !fcx.tcx.features().unsized_locals { - let id = fcx.tcx.hir().get_parent_node(id); + let id = fcx.tcx.hir().parent_id(id); unsized_return = self.is_return_ty_unsized(fcx, id); } } @@ -1668,7 +1668,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let mut pointing_at_return_type = false; let mut fn_output = None; - let parent_id = fcx.tcx.hir().get_parent_node(id); + let parent_id = fcx.tcx.hir().parent_id(id); let parent = fcx.tcx.hir().get(parent_id); if let Some(expr) = expression && let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(&hir::Closure { body, .. }), .. }) = parent diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 1360383a75a9..6f1af904c028 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -211,7 +211,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, error: Option>, ) { - let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let parent = self.tcx.hir().parent_id(expr.hir_id); match (self.tcx.hir().find(parent), error) { (Some(hir::Node::Local(hir::Local { ty: Some(ty), init: Some(init), .. })), _) if init.hir_id == expr.hir_id => @@ -258,7 +258,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) { - let parent = self.tcx.hir().get_parent_node(pat.hir_id); + let parent = self.tcx.hir().parent_id(pat.hir_id); primary_span = pat.span; secondary_span = pat.span; match self.tcx.hir().find(parent) { @@ -326,7 +326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, error: Option>, ) { - let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let parent = self.tcx.hir().parent_id(expr.hir_id); let Some(TypeError::Sorts(ExpectedFound { expected, .. })) = error else {return;}; let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(lhs, rhs, _), .. @@ -510,7 +510,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Unroll desugaring, to make sure this works for `for` loops etc. loop { - parent = self.tcx.hir().get_parent_node(id); + parent = self.tcx.hir().parent_id(id); if let Some(parent_span) = self.tcx.hir().opt_span(parent) { if parent_span.find_ancestor_inside(expr.span).is_some() { // The parent node is part of the same span, so is the result of the @@ -790,12 +790,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let local_parent = self.tcx.hir().get_parent_node(local_id); + let local_parent = self.tcx.hir().parent_id(local_id); let Some(Node::Param(hir::Param { hir_id: param_hir_id, .. })) = self.tcx.hir().find(local_parent) else { return None; }; - let param_parent = self.tcx.hir().get_parent_node(*param_hir_id); + let param_parent = self.tcx.hir().parent_id(*param_hir_id); let Some(Node::Expr(hir::Expr { hir_id: expr_hir_id, kind: hir::ExprKind::Closure(hir::Closure { fn_decl: closure_fn_decl, .. }), @@ -804,7 +804,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let expr_parent = self.tcx.hir().get_parent_node(*expr_hir_id); + let expr_parent = self.tcx.hir().parent_id(*expr_hir_id); let hir = self.tcx.hir().find(expr_parent); let closure_params_len = closure_fn_decl.inputs.len(); let ( @@ -857,7 +857,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }?; - match hir.find(hir.get_parent_node(expr.hir_id))? { + match hir.find(hir.parent_id(expr.hir_id))? { Node::ExprField(field) => { if field.ident.name == local.name && field.is_shorthand { return Some(local.name); @@ -883,7 +883,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Returns whether the given expression is an `else if`. pub(crate) fn is_else_if_block(&self, expr: &hir::Expr<'_>) -> bool { if let hir::ExprKind::If(..) = expr.kind { - let parent_id = self.tcx.hir().get_parent_node(expr.hir_id); + let parent_id = self.tcx.hir().parent_id(expr.hir_id); if let Some(Node::Expr(hir::Expr { kind: hir::ExprKind::If(_, _, Some(else_expr)), .. @@ -1040,7 +1040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(..), .. - })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) + })) = self.tcx.hir().find(self.tcx.hir().parent_id(expr.hir_id)) { if mutability.is_mut() { // Suppressing this diagnostic, we'll properly print it in `check_expr_assign` @@ -1268,7 +1268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut sugg = vec![]; if let Some(hir::Node::ExprField(field)) = - self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) + self.tcx.hir().find(self.tcx.hir().parent_id(expr.hir_id)) { // `expr` is a literal field for a struct, only suggest if appropriate if field.is_shorthand { @@ -1625,7 +1625,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [start, end], _, ) = expr.kind else { return; }; - let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let parent = self.tcx.hir().parent_id(expr.hir_id); if let Some(hir::Node::ExprField(_)) = self.tcx.hir().find(parent) { // Ignore `Foo { field: a..Default::default() }` return; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b8b4e8736631..ee5578a8de63 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -920,7 +920,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { original_expr_id: HirId, then: impl FnOnce(&hir::Expr<'_>), ) { - let mut parent = self.tcx.hir().get_parent_node(original_expr_id); + let mut parent = self.tcx.hir().parent_id(original_expr_id); while let Some(node) = self.tcx.hir().find(parent) { match node { hir::Node::Expr(hir::Expr { @@ -959,7 +959,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | hir::Node::TraitItem(_) | hir::Node::Crate(_) => break, _ => { - parent = self.tcx.hir().get_parent_node(parent); + parent = self.tcx.hir().parent_id(parent); } } } @@ -1083,7 +1083,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = - hir.get(hir.get_parent_node(hir.get_parent_node(expr.hir_id))) + hir.get(hir.parent_id(hir.parent_id(expr.hir_id))) { err.span_suggestion_verbose( expr.span.shrink_to_lo(), @@ -2462,7 +2462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(field.span, "method, not a field"); let expr_is_call = if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = - self.tcx.hir().get(self.tcx.hir().get_parent_node(expr.hir_id)) + self.tcx.hir().get(self.tcx.hir().parent_id(expr.hir_id)) { expr.hir_id == callee.hir_id } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 150e917c7398..a452dcc5014e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1436,7 +1436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut contained_in_place = false; while let hir::Node::Expr(parent_expr) = - self.tcx.hir().get(self.tcx.hir().get_parent_node(expr_id)) + self.tcx.hir().get(self.tcx.hir().parent_id(expr_id)) { match &parent_expr.kind { hir::ExprKind::Assign(lhs, ..) | hir::ExprKind::AssignOp(_, lhs, ..) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index d342d96a10fa..fbb4da153b88 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1803,7 +1803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id: call_hir_id, span: call_span, .. - }) = hir.get(hir.get_parent_node(expr.hir_id)) + }) = hir.get(hir.parent_id(expr.hir_id)) && callee.hir_id == expr.hir_id { if self.closure_span_overlaps_error(error, *call_span) { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 322e11c978f4..066e98c74578 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -32,7 +32,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.typeck_results .borrow() .liberated_fn_sigs() - .get(self.tcx.hir().get_parent_node(self.body_id)) + .get(self.tcx.hir().parent_id(self.body_id)) .copied() } @@ -642,7 +642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check if the parent expression is a call to Pin::new. If it // is and we were expecting a Box, ergo Pin>, we // can suggest Box::pin. - let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let parent = self.tcx.hir().parent_id(expr.hir_id); let Some(Node::Expr(Expr { kind: ExprKind::Call(fn_name, _), .. })) = self.tcx.hir().find(parent) else { return false; }; diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index b06927f9662b..26d4e7d1df37 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -224,7 +224,7 @@ fn typeck_with_fallback<'tcx>( _ => None, }) .unwrap_or_else(|| match tcx.hir().get(id) { - Node::AnonConst(_) => match tcx.hir().get(tcx.hir().get_parent_node(id)) { + Node::AnonConst(_) => match tcx.hir().get(tcx.hir().parent_id(id)) { Node::Expr(&hir::Expr { kind: hir::ExprKind::ConstBlock(ref anon_const), .. diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 71c3803e64fa..ccee9b2554ce 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -116,7 +116,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sugg_span = if let SelfSource::MethodCall(expr) = source { // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing. - self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span + self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)).span } else { span }; @@ -334,7 +334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(rcvr_expr) = source { self.suggest_fn_call(&mut err, rcvr_expr, rcvr_ty, |output_ty| { let call_expr = - self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(rcvr_expr.hir_id)); + self.tcx.hir().expect_expr(self.tcx.hir().parent_id(rcvr_expr.hir_id)); let probe = self.lookup_probe(item_name, output_ty, call_expr, ProbeScope::AllTraits); probe.is_ok() @@ -916,8 +916,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let msg = "remove this method call"; let mut fallback_span = true; if let SelfSource::MethodCall(expr) = source { - let call_expr = - self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); + let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); if let Some(span) = call_expr.span.trim_start(expr.span) { err.span_suggestion(span, msg, "", Applicability::MachineApplicable); fallback_span = false; @@ -1270,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else { - let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id)); + let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id)); if let Some(span) = call_expr.span.trim_start(item_name.span) { err.span_suggestion( @@ -1452,7 +1451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let filename = tcx.sess.source_map().span_to_filename(span); let parent_node = - self.tcx.hir().get(self.tcx.hir().get_parent_node(hir_id)); + self.tcx.hir().get(self.tcx.hir().parent_id(hir_id)); let msg = format!( "you must specify a type for this binding, like `{}`", concrete_type, @@ -1525,7 +1524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut visitor = LetVisitor { result: None, ident_name: seg1.ident.name }; visitor.visit_body(&body); - let parent = self.tcx.hir().get_parent_node(seg1.hir_id); + let parent = self.tcx.hir().parent_id(seg1.hir_id); if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) && let Some(expr) = visitor.result && let Some(self_ty) = self.node_ty_opt(expr.hir_id) @@ -1563,7 +1562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let Some((fields, substs)) = self.get_field_candidates_considering_privacy(span, actual, mod_id) { - let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)); + let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); let lang_items = self.tcx.lang_items(); let never_mention_traits = [ @@ -1633,7 +1632,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { let tcx = self.tcx; let SelfSource::MethodCall(expr) = source else { return; }; - let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id)); + let call_expr = tcx.hir().expect_expr(tcx.hir().parent_id(expr.hir_id)); let ty::Adt(kind, substs) = actual.kind() else { return; }; match kind.adt_kind() { @@ -2594,7 +2593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; } - let parent = self.tcx.hir().get_parent_node(expr.hir_id); + let parent = self.tcx.hir().parent_id(expr.hir_id); if let Some(Node::Expr(call_expr)) = self.tcx.hir().find(parent) && let hir::ExprKind::MethodCall( hir::PathSegment { ident: method_name, .. }, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 28e959b7c6a1..ff3b347ee018 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -692,7 +692,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; if let PatKind::Ref(inner, mutbl) = pat.kind && let PatKind::Binding(_, _, binding, ..) = inner.kind { - let binding_parent_id = tcx.hir().get_parent_node(pat.hir_id); + let binding_parent_id = tcx.hir().parent_id(pat.hir_id); let binding_parent = tcx.hir().get(binding_parent_id); debug!(?inner, ?pat, ?binding_parent); @@ -936,7 +936,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { res.descr(), ), ); - match self.tcx.hir().get(self.tcx.hir().get_parent_node(pat.hir_id)) { + match self.tcx.hir().get(self.tcx.hir().parent_id(pat.hir_id)) { hir::Node::PatField(..) => { e.span_suggestion_verbose( ident.span.shrink_to_hi(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 30ca9f41d6e6..1ebfde16df9a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -411,7 +411,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span: Span, ) { let hir = self.tcx.hir(); - let fn_hir_id = hir.get_parent_node(cause.body_id); + let fn_hir_id = hir.parent_id(cause.body_id); if let Some(node) = self.tcx.hir().find(fn_hir_id) && let hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_sig, _, body_id), .. @@ -585,9 +585,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir::StmtKind::Local(local) = &stmt.kind else { continue; }; local.pat.walk(&mut find_compatible_candidates); } - match hir.find(hir.get_parent_node(blk.hir_id)) { + match hir.find(hir.parent_id(blk.hir_id)) { Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => { - match hir.find(hir.get_parent_node(*hir_id)) { + match hir.find(hir.parent_id(*hir_id)) { Some(hir::Node::Arm(hir::Arm { pat, .. })) => { pat.walk(&mut find_compatible_candidates); } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 10d8db5393da..3c2f2e9417a5 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1526,7 +1526,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { let map = cx.tcx.hir(); - if matches!(map.get(map.get_parent_node(field.hir_id)), Node::Variant(_)) { + if matches!(map.get(map.parent_id(field.hir_id)), Node::Variant(_)) { return; } self.perform_lint(cx, "field", field.def_id, field.vis_span, false); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 4f92661dbd33..96084a50984e 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { TyKind::Path(QPath::Resolved(_, path)) => { if lint_ty_kind_usage(cx, &path.res) { let hir = cx.tcx.hir(); - let span = match hir.find(hir.get_parent_node(ty.hir_id)) { + let span = match hir.find(hir.parent_id(ty.hir_id)) { Some(Node::Pat(Pat { kind: PatKind::Path(qpath) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 91fcd6d690ee..a4182c121ed0 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -444,8 +444,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { if let PatKind::Binding(_, hid, ident, _) = p.kind { - if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) - { + if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().parent_id(hid)) { if !field.is_shorthand { // Only check if a new name has been introduced, to avoid warning // on both the struct definition and this pattern. diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 8e27bc03c489..9b67ab38f909 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -127,9 +127,9 @@ fn lint_overflowing_range_endpoint<'tcx>( ) -> bool { // We only want to handle exclusive (`..`) ranges, // which are represented as `ExprKind::Struct`. - let par_id = cx.tcx.hir().get_parent_node(expr.hir_id); + let par_id = cx.tcx.hir().parent_id(expr.hir_id); let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false }; - let field_par_id = cx.tcx.hir().get_parent_node(field.hir_id); + let field_par_id = cx.tcx.hir().parent_id(field.hir_id); let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false }; if !is_range_literal(struct_expr) { return false; @@ -404,7 +404,7 @@ fn lint_uint_literal<'tcx>( _ => bug!(), }; if lit_val < min || lit_val > max { - let parent_id = cx.tcx.hir().get_parent_node(e.hir_id); + let parent_id = cx.tcx.hir().parent_id(e.hir_id); if let Node::Expr(par_e) = cx.tcx.hir().get(parent_id) { match par_e.kind { hir::ExprKind::Cast(..) => { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index d799d3a5ad77..e00949d45a27 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -69,7 +69,7 @@ impl<'hir> Iterator for ParentHirIterator<'hir> { } loop { // There are nodes that do not have entries, so we need to skip them. - let parent_id = self.map.get_parent_node(self.current_id); + let parent_id = self.map.parent_id(self.current_id); if parent_id == self.current_id { self.current_id = CRATE_HIR_ID; @@ -246,7 +246,7 @@ impl<'hir> Map<'hir> { }, Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { - let ctor_of = match self.find(self.get_parent_node(hir_id)) { + let ctor_of = match self.find(self.parent_id(hir_id)) { Some(Node::Item(..)) => def::CtorOf::Struct, Some(Node::Variant(..)) => def::CtorOf::Variant, _ => unreachable!(), @@ -257,7 +257,7 @@ impl<'hir> Map<'hir> { } } Node::AnonConst(_) => { - let inline = match self.find(self.get_parent_node(hir_id)) { + let inline = match self.find(self.parent_id(hir_id)) { Some(Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })) if anon_const.hir_id == hir_id => true, @@ -312,7 +312,7 @@ impl<'hir> Map<'hir> { } #[track_caller] - pub fn get_parent_node(self, hir_id: HirId) -> HirId { + pub fn parent_id(self, hir_id: HirId) -> HirId { self.find_parent_node(hir_id) .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id))) } @@ -414,7 +414,7 @@ impl<'hir> Map<'hir> { /// which this is the body of, i.e., a `fn`, `const` or `static` /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(self, BodyId { hir_id }: BodyId) -> HirId { - let parent = self.get_parent_node(hir_id); + let parent = self.parent_id(hir_id); assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id)), "{hir_id:?}"); parent } @@ -642,21 +642,21 @@ impl<'hir> Map<'hir> { } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` - /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. + /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_id_iter(self, current_id: HirId) -> impl Iterator + 'hir { ParentHirIterator { current_id, map: self } } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` - /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. + /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_iter(self, current_id: HirId) -> impl Iterator)> { self.parent_id_iter(current_id).filter_map(move |id| Some((id, self.find(id)?))) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` - /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`. + /// until the crate root is reached. Prefer this over your own loop using `parent_id`. #[inline] pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> { ParentOwnerIterator { current_id, map: self } @@ -664,7 +664,7 @@ impl<'hir> Map<'hir> { /// Checks if the node is left-hand side of an assignment. pub fn is_lhs(self, id: HirId) -> bool { - match self.find(self.get_parent_node(id)) { + match self.find(self.parent_id(id)) { Some(Node::Expr(expr)) => match expr.kind { ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id, _ => false, @@ -892,7 +892,7 @@ impl<'hir> Map<'hir> { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::opt_span`. - Node::Ctor(..) => match self.find(self.get_parent_node(id))? { + Node::Ctor(..) => match self.find(self.parent_id(id))? { Node::Item(item) => Some(item.ident), Node::Variant(variant) => Some(variant.ident), _ => unreachable!(), @@ -1021,7 +1021,7 @@ impl<'hir> Map<'hir> { ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, - Node::Ctor(_) => return self.opt_span(self.get_parent_node(hir_id)), + Node::Ctor(_) => return self.opt_span(self.parent_id(hir_id)), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl_span, .. }), span, @@ -1063,7 +1063,7 @@ impl<'hir> Map<'hir> { Node::PatField(field) => field.span, Node::Arm(arm) => arm.span, Node::Block(block) => block.span, - Node::Ctor(..) => self.span_with_body(self.get_parent_node(hir_id)), + Node::Ctor(..) => self.span_with_body(self.parent_id(hir_id)), Node::Lifetime(lifetime) => lifetime.ident.span, Node::GenericParam(param) => param.span, Node::Infer(i) => i.span, @@ -1093,7 +1093,7 @@ impl<'hir> Map<'hir> { /// Returns the HirId of `N` in `struct Foo` when /// called with the HirId for the `{ ... }` anon const pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option { - match self.get(self.get_parent_node(anon_const)) { + match self.get(self.parent_id(anon_const)) { Node::GenericParam(GenericParam { def_id: param_id, kind: GenericParamKind::Const { .. }, diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 51df42f6d14e..eb48b325e84e 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -182,7 +182,7 @@ impl TyCtxt<'_> { if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) { return id; } - let next = hir.get_parent_node(id); + let next = hir.parent_id(id); if next == id { bug!("lint traversal reached the root of the crate"); } diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 14d07608a780..e1aa7fea441c 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -457,7 +457,7 @@ impl<'tcx> TyCtxt<'tcx> { .def_id .as_local() .map(|id| hir.local_def_id_to_hir_id(id)) - .and_then(|id| self.hir().find(self.hir().get_parent_node(id))) + .and_then(|id| self.hir().find(self.hir().parent_id(id))) .as_ref() .and_then(|node| node.generics()) { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index a94d8d6c6431..e7ee0d9e908e 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -247,14 +247,14 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId) -> bool { let hir = self.tcx.hir(); - let parent = hir.get_parent_node(pat_id); + let parent = hir.parent_id(pat_id); // First, figure out if the given pattern is part of a let chain, // and if so, obtain the top node of the chain. let mut top = parent; let mut part_of_chain = false; loop { - let new_top = hir.get_parent_node(top); + let new_top = hir.parent_id(top); if let hir::Node::Expr( hir::Expr { kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs), @@ -1054,7 +1054,7 @@ pub enum LetSource { fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource { let hir = tcx.hir(); - let parent = hir.get_parent_node(pat_id); + let parent = hir.parent_id(pat_id); let_source_parent(tcx, parent, Some(pat_id)) } @@ -1073,7 +1073,7 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option) -> L _ => {} } - let parent_parent = hir.get_parent_node(parent); + let parent_parent = hir.parent_id(parent); let parent_parent_node = hir.get(parent_parent); match parent_parent_node { hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), .. }) => { @@ -1085,8 +1085,8 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option) -> L _ => {} } - let parent_parent_parent = hir.get_parent_node(parent_parent); - let parent_parent_parent_parent = hir.get_parent_node(parent_parent_parent); + let parent_parent_parent = hir.parent_id(parent_parent); + let parent_parent_parent_parent = hir.parent_id(parent_parent_parent); let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent); if let hir::Node::Expr(hir::Expr { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 72d38aeac7a0..ef241c5398d4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -2141,7 +2141,7 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { if !old_error_set_ancestry.insert(id) { break; } - let parent = tcx.hir().get_parent_node(id); + let parent = tcx.hir().parent_id(id); if parent == id { break; } diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 6afd5fe5a7f2..a8d82de02b75 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -600,7 +600,7 @@ impl<'tcx> SaveContext<'tcx> { if seg.res != Res::Err { seg.res } else { - let parent_node = self.tcx.hir().get_parent_node(hir_id); + let parent_node = self.tcx.hir().parent_id(hir_id); self.get_path_res(parent_node) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index 9bfe527647de..b0a730c8ad16 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -117,7 +117,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { Some(if movability.is_some() { "an async closure" } else { "a closure" }) }), hir::Node::Expr(hir::Expr { .. }) => { - let parent_hid = hir.get_parent_node(hir_id); + let parent_hid = hir.parent_id(hir_id); if parent_hid != hir_id { self.describe_enclosure(parent_hid) } else { None } } _ => None, 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 7c21a1047bcb..bf5e06268e96 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -838,7 +838,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let hir = self.tcx.hir(); let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?); - let parent_node = hir.get_parent_node(hir_id); + let parent_node = hir.parent_id(hir_id); match hir.find(parent_node) { Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => { get_name(err, &local.pat.kind) @@ -1421,7 +1421,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { let hir = self.tcx.hir(); - let parent_node = hir.get_parent_node(obligation.cause.body_id); + let parent_node = hir.parent_id(obligation.cause.body_id); let node = hir.find(parent_node); if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), .. })) = node && let hir::ExprKind::Block(blk, _) = &hir.body(*body_id).value.kind @@ -1458,7 +1458,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option { let hir = self.tcx.hir(); - let parent_node = hir.get_parent_node(obligation.cause.body_id); + let parent_node = hir.parent_id(obligation.cause.body_id); let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, ..), .. })) = hir.find(parent_node) else { return None; }; @@ -1483,7 +1483,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let hir = self.tcx.hir(); - let fn_hir_id = hir.get_parent_node(obligation.cause.body_id); + let fn_hir_id = hir.parent_id(obligation.cause.body_id); let node = hir.find(fn_hir_id); let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, _, body_id), @@ -1695,7 +1695,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } let hir = self.tcx.hir(); - let parent_node = hir.get_parent_node(obligation.cause.body_id); + let parent_node = hir.parent_id(obligation.cause.body_id); let node = hir.find(parent_node); if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) = node @@ -2291,7 +2291,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let expr = hir.expect_expr(expr_id); debug!("target_ty evaluated from {:?}", expr); - let parent = hir.get_parent_node(expr_id); + let parent = hir.parent_id(expr_id); if let Some(hir::Node::Expr(e)) = hir.find(parent) { let parent_span = hir.span(parent); let parent_did = parent.owner.to_def_id(); @@ -2512,7 +2512,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } ObligationCauseCode::VariableType(hir_id) => { - let parent_node = self.tcx.hir().get_parent_node(hir_id); + let parent_node = self.tcx.hir().parent_id(hir_id); match self.tcx.hir().find(parent_node) { Some(Node::Local(hir::Local { ty: Some(ty), .. })) => { err.span_suggestion_verbose( @@ -2992,7 +2992,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { span: Span, ) { let body_hir_id = obligation.cause.body_id; - let item_id = self.tcx.hir().get_parent_node(body_hir_id); + let item_id = self.tcx.hir().parent_id(body_hir_id); if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(self.tcx.hir().local_def_id(item_id)) @@ -3219,7 +3219,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) && let Some(hir::Node::Local(local)) = self.tcx.hir().find(parent_hir_id) && let Some(binding_expr) = local.init { @@ -3287,7 +3287,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) && let Some(parent) = self.tcx.hir().find(parent_hir_id) { // We've reached the root of the method call chain... diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e2d10f550c32..e17b8346c0ee 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -161,7 +161,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..), .. }) => { - let parent_hir_id = tcx.hir().get_parent_node(hir_id); + let parent_hir_id = tcx.hir().parent_id(hir_id); match tcx.hir().get(parent_hir_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(hir::Impl { constness, .. }), diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 1d09adec12f3..58b7b9829a10 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -131,7 +131,7 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { _ => return false, } - matches!(map.find(map.get_parent_node(id)), Some(Node::Param(_))) + matches!(map.find(map.parent_id(id)), Some(Node::Param(_))) } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { @@ -156,8 +156,8 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { let map = &self.cx.tcx.hir(); if is_argument(*map, cmt.hir_id) { // Skip closure arguments - let parent_id = map.get_parent_node(cmt.hir_id); - if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) { + let parent_id = map.parent_id(cmt.hir_id); + if let Some(Node::Expr(..)) = map.find(map.parent_id(parent_id)) { return; } diff --git a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs index cf35b1f175c6..bdeddf44df7b 100644 --- a/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs +++ b/src/tools/clippy/clippy_lints/src/index_refutable_slice.rs @@ -251,7 +251,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { let map = cx.tcx.hir(); // Checking for slice indexing - let parent_id = map.get_parent_node(expr.hir_id); + let parent_id = map.parent_id(expr.hir_id); if let Some(hir::Node::Expr(parent_expr)) = map.find(parent_id); if let hir::ExprKind::Index(_, index_expr) = parent_expr.kind; if let Some((Constant::Int(index_value), _)) = constant(cx, cx.typeck_results(), index_expr); @@ -259,7 +259,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SliceIndexLintingVisitor<'a, 'tcx> { if index_value < max_suggested_slice; // Make sure that this slice index is read only - let maybe_addrof_id = map.get_parent_node(parent_id); + let maybe_addrof_id = map.parent_id(parent_id); if let Some(hir::Node::Expr(maybe_addrof_expr)) = map.find(maybe_addrof_id); if let hir::ExprKind::AddrOf(_kind, hir::Mutability::Not, _inner_expr) = maybe_addrof_expr.kind; then { diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs index 07edee46fa65..540656a2cd99 100644 --- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs +++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs @@ -63,7 +63,7 @@ pub(super) fn check<'tcx>( if let Node::Pat(pat) = node; if let PatKind::Binding(bind_ann, ..) = pat.kind; if !matches!(bind_ann, BindingAnnotation(_, Mutability::Mut)); - let parent_node = cx.tcx.hir().get_parent_node(hir_id); + let parent_node = cx.tcx.hir().parent_id(hir_id); if let Some(Node::Local(parent_let_expr)) = cx.tcx.hir().find(parent_node); if let Some(init) = parent_let_expr.init; then { diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 8d447c37150b..494fde395e93 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { && let Some(hir_id) = path_to_local(expr3) && let Some(Node::Pat(_)) = cx.tcx.hir().find(hir_id) { // Apply only to params or locals with annotated types - match cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + match cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { Some(Node::Param(..)) => (), Some(Node::Local(local)) => { let Some(ty) = local.ty else { return }; diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index c94a1f763306..abe9d231f4aa 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -140,8 +140,8 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option { let map = &cx.tcx.hir(); - if let Some(Node::Expr(parent_arm_expr)) = map.find(map.get_parent_node(ex.hir_id)) { - return match map.find(map.get_parent_node(parent_arm_expr.hir_id)) { + if let Some(Node::Expr(parent_arm_expr)) = map.find(map.parent_id(ex.hir_id)) { + return match map.find(map.parent_id(parent_arm_expr.hir_id)) { Some(Node::Local(parent_let_expr)) => Some(AssignmentExpr::Local { span: parent_let_expr.span, pat_span: parent_let_expr.pat.span(), @@ -183,7 +183,7 @@ fn sugg_with_curlies<'a>( // If the parent is already an arm, and the body is another match statement, // we need curly braces around suggestion - let parent_node_id = cx.tcx.hir().get_parent_node(match_expr.hir_id); + let parent_node_id = cx.tcx.hir().parent_id(match_expr.hir_id); if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) { if let ExprKind::Match(..) = arm.body.kind { cbrace_end = format!("\n{indent}}}"); diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index 321fa4b7f999..f0be7771bb1a 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -186,7 +186,7 @@ fn check_for_unsequenced_reads(vis: &mut ReadVisitor<'_, '_>) { let map = &vis.cx.tcx.hir(); let mut cur_id = vis.write_expr.hir_id; loop { - let parent_id = map.get_parent_node(cur_id); + let parent_id = map.parent_id(cur_id); if parent_id == cur_id { break; } diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 2f0b7ce16e51..58c54280a234 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 2a3bd4ee6ce6..07fd321d69fc 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -366,7 +366,7 @@ impl<'tcx> LateLintPass<'tcx> for NonCopyConst { let mut dereferenced_expr = expr; let mut needs_check_adjustment = true; loop { - let parent_id = cx.tcx.hir().get_parent_node(cur_expr.hir_id); + let parent_id = cx.tcx.hir().parent_id(cur_expr.hir_id); if parent_id == cur_expr.hir_id { break; } diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 75add4ee4aad..f96a19b27235 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -299,7 +299,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index ef9f740f7047..ac4f8789a434 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { return; } let map = &cx.tcx.hir(); - let opt_parent_node = map.find(map.get_parent_node(expr.hir_id)); + let opt_parent_node = map.find(map.parent_id(expr.hir_id)); if_chain! { if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; if is_questionmark_desugar_marked_call(parent_expr); @@ -192,7 +192,7 @@ fn fmt_stmts_and_call( let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent))); // expr is not in a block statement or result expression position, wrap in a block - let parent_node = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(call_expr.hir_id)); + let parent_node = cx.tcx.hir().find(cx.tcx.hir().parent_id(call_expr.hir_id)); if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) { let block_indent = call_expr_indent + 4; stmts_and_call_snippet = diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 60b46854b4ff..63f4f01b0877 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { } // Abort if the method is implementing a trait or of it a trait method. - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index 929544cd69d5..a177ae507bbe 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) - fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> { let map = cx.tcx.hir(); - match map.find(map.get_parent_node(hir_id)) { + match map.find(map.parent_id(hir_id)) { Some(hir::Node::Local(local)) => Some(local), Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id), _ => None, diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs index 393988dbad38..7144363637a0 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs @@ -219,7 +219,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option match cx.qpath_res(qpath, expr.hir_id) { Res::Local(hir_id) => { - let parent_id = cx.tcx.hir().get_parent_node(hir_id); + let parent_id = cx.tcx.hir().parent_id(hir_id); if let Some(Node::Local(Local { init: Some(init), .. })) = cx.tcx.hir().find(parent_id) { path_to_matched_type(cx, init) } else { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index d863609b6a72..63d0938169a8 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -174,7 +174,7 @@ pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option< if_chain! { if let Some(Node::Pat(pat)) = hir.find(hir_id); if matches!(pat.kind, PatKind::Binding(BindingAnnotation::NONE, ..)); - let parent = hir.get_parent_node(hir_id); + let parent = hir.parent_id(hir_id); if let Some(Node::Local(local)) = hir.find(parent); then { return local.init; @@ -2075,7 +2075,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { /// } /// ``` pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool { - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false From 6af339dbfac612c13ae3811b70a066f6babc5e02 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 3 Jan 2023 07:31:33 +0000 Subject: [PATCH 117/223] rename find_parent_node to opt_parent_id --- compiler/rustc_const_eval/src/transform/check_consts/mod.rs | 2 +- .../src/structured_errors/wrong_number_of_generic_args.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 2 +- .../generator_interior/drop_ranges/record_consumed_borrow.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 4 ++-- compiler/rustc_middle/src/mir/mod.rs | 2 +- src/librustdoc/passes/check_doc_test_visibility.rs | 2 +- .../clippy_lints/src/casts/cast_slice_different_sizes.rs | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 655ec345ed37..0a90572d39e3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -115,7 +115,7 @@ fn is_parent_const_stable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool { let local_def_id = def_id.expect_local(); let hir_id = tcx.local_def_id_to_hir_id(local_def_id); - let Some(parent) = tcx.hir().find_parent_node(hir_id) else { return false }; + let Some(parent) = tcx.hir().opt_parent_id(hir_id) else { return false }; let parent_def = tcx.hir().get(parent); if !matches!( diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 4451db19f5c1..3df8f776eded 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -716,7 +716,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { num = num_trait_generics_except_self, ); - if let Some(parent_node) = self.tcx.hir().find_parent_node(self.path_segment.hir_id) + if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id) && let Some(parent_node) = self.tcx.hir().find(parent_node) && let hir::Node::Expr(expr) = parent_node { match expr.kind { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index ee5578a8de63..7b66422cce67 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -943,7 +943,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) => { // Check if our original expression is a child of the condition of a while loop let expr_is_ancestor = std::iter::successors(Some(original_expr_id), |id| { - self.tcx.hir().find_parent_node(*id) + self.tcx.hir().opt_parent_id(*id) }) .take_while(|id| *id != parent) .any(|id| id == expr.hir_id); diff --git a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs index bfe95852aa7b..472205be7b5e 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/drop_ranges/record_consumed_borrow.rs @@ -140,7 +140,7 @@ impl<'tcx> expr_use_visitor::Delegate<'tcx> for ExprUseDelegate<'tcx> { diag_expr_id: HirId, ) { let hir = self.tcx.hir(); - let parent = match hir.find_parent_node(place_with_id.hir_id) { + let parent = match hir.opt_parent_id(place_with_id.hir_id) { Some(parent) => parent, None => place_with_id.hir_id, }; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index e00949d45a27..65a49a5fe85e 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -298,7 +298,7 @@ impl<'hir> Map<'hir> { /// Finds the id of the parent node to this one. /// /// If calling repeatedly and iterating over parents, prefer [`Map::parent_iter`]. - pub fn find_parent_node(self, id: HirId) -> Option { + pub fn opt_parent_id(self, id: HirId) -> Option { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) } else { @@ -313,7 +313,7 @@ impl<'hir> Map<'hir> { #[track_caller] pub fn parent_id(self, hir_id: HirId) -> HirId { - self.find_parent_node(hir_id) + self.opt_parent_id(hir_id) .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id))) } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index a89e6566d56a..14bdff4568f5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2506,7 +2506,7 @@ impl<'tcx> ConstantKind<'tcx> { } let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - let parent_substs = if let Some(parent_hir_id) = tcx.hir().find_parent_node(hir_id) { + let parent_substs = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) { if let Some(parent_did) = tcx.hir().opt_local_def_id(parent_hir_id) { InternalSubsts::identity_for_item(tcx, parent_did.to_def_id()) } else { diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 057d2fdd9d5f..6aa2dda980cf 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -82,7 +82,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.item_id.expect_def_id().expect_local()); // check if parent is trait impl - if let Some(parent_hir_id) = cx.tcx.hir().find_parent_node(hir_id) { + if let Some(parent_hir_id) = cx.tcx.hir().opt_parent_id(hir_id) { if let Some(parent_node) = cx.tcx.hir().find(parent_hir_id) { if matches!( parent_node, diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs index c8e54d7b8e0c..27cc5a1c3f04 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_slice_different_sizes.rs @@ -68,7 +68,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv fn is_child_of_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool { let map = cx.tcx.hir(); if_chain! { - if let Some(parent_id) = map.find_parent_node(expr.hir_id); + if let Some(parent_id) = map.opt_parent_id(expr.hir_id); if let Some(parent) = map.find(parent_id); then { let expr = match parent { From b1b19bd8519ec2645578ecfcc55a438324ee5908 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 3 Jan 2023 17:30:35 +0000 Subject: [PATCH 118/223] get_parent and find_parent --- compiler/rustc_hir/src/hir.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/generics_of.rs | 4 +- .../rustc_hir_analysis/src/collect/type_of.rs | 6 +- compiler/rustc_hir_typeck/src/_match.rs | 5 +- compiler/rustc_hir_typeck/src/demand.rs | 11 +-- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 2 +- .../src/infer/error_reporting/suggest.rs | 73 +++++++++---------- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/internal.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_lint/src/types.rs | 3 +- compiler/rustc_middle/src/hir/map/mod.rs | 18 +++-- compiler/rustc_middle/src/ty/error.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 6 +- src/tools/clippy/clippy_lints/src/escape.rs | 4 +- .../clippy_lints/src/manual_rem_euclid.rs | 2 +- .../src/matches/match_single_binding.rs | 7 +- .../src/needless_pass_by_value.rs | 2 +- .../clippy_lints/src/pass_by_ref_or_value.rs | 2 +- .../clippy_lints/src/unit_types/unit_arg.rs | 4 +- .../clippy_lints/src/unnecessary_wraps.rs | 2 +- .../internal_lints/metadata_collector.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 +- 29 files changed, 88 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 4f74dbe99e3d..bc897ed8112e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3460,7 +3460,7 @@ impl<'hir> Node<'hir> { /// ```ignore (illustrative) /// ctor /// .ctor_hir_id() - /// .and_then(|ctor_id| tcx.hir().find(tcx.hir().parent_id(ctor_id))) + /// .and_then(|ctor_id| tcx.hir().find_parent(ctor_id)) /// .and_then(|parent| parent.ident()) /// ``` pub fn ident(&self) -> Option { diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 93b91b3c9c62..1b334f65b9ec 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2936,7 +2936,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), ident, .. }) = hir.get(fn_hir_id) else { return None }; let hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(i), .. }) = - hir.get(hir.parent_id(fn_hir_id)) else { bug!("ImplItem should have Impl parent") }; + hir.get_parent(fn_hir_id) else { bug!("ImplItem should have Impl parent") }; let trait_ref = self.instantiate_mono_trait_ref( i.of_trait.as_ref()?, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index fb732d7f9452..86ee18c04ec0 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1108,7 +1108,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => { // Do not try to infer the return type for a impl method coming from a trait if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = - tcx.hir().get(tcx.hir().parent_id(hir_id)) + tcx.hir().get_parent(hir_id) && i.of_trait.is_some() { >::ty_of_fn( diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 8ff96869b557..96221c3e3d86 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -103,7 +103,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // `min_const_generics`. Some(parent_def_id.to_def_id()) } else { - let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); + let parent_node = tcx.hir().get_parent(hir_id); match parent_node { // HACK(eddyb) this provides the correct generics for repeat // expressions' count (i.e. `N` in `[x; N]`), and explicit @@ -320,7 +320,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { // provide junk type parameter defs for const blocks. if let Node::AnonConst(_) = node { - let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); + let parent_node = tcx.hir().get_parent(hir_id); if let Node::Expr(&Expr { kind: ExprKind::ConstBlock(_), .. }) = parent_node { params.push(ty::GenericParamDef { index: next_index(), diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 1c8acf6590de..1f9a9f80302e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -402,7 +402,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } Node::AnonConst(_) => { - let parent_node = tcx.hir().get(tcx.hir().parent_id(hir_id)); + let parent_node = tcx.hir().get_parent(hir_id); match parent_node { Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) @@ -445,7 +445,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .. }, ) if let Node::TraitRef(trait_ref) = - tcx.hir().get(tcx.hir().parent_id(binding_id)) + tcx.hir().get_parent(binding_id) && e.hir_id == hir_id => { let Some(trait_def_id) = trait_ref.trait_def_id() else { @@ -472,7 +472,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { Node::TypeBinding( binding @ &TypeBinding { hir_id: binding_id, gen_args, ref kind, .. }, ) if let Node::TraitRef(trait_ref) = - tcx.hir().get(tcx.hir().parent_id(binding_id)) + tcx.hir().get_parent(binding_id) && let Some((idx, _)) = gen_args.args.iter().enumerate().find(|(_, arg)| { if let GenericArg::Const(ct) = arg { diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 7659b2d0a0b8..71a469784cd8 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -294,10 +294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if let hir::Node::Block(block) = node { // check that the body's parent is an fn - let parent = self - .tcx - .hir() - .get(self.tcx.hir().parent_id(self.tcx.hir().parent_id(block.hir_id))); + let parent = self.tcx.hir().get_parent(self.tcx.hir().parent_id(block.hir_id)); if let (Some(expr), hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })) = (&block.expr, parent) { diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6f1af904c028..9c6c53abf074 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -258,10 +258,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Path { res: hir::def::Res::Local(hir_id), .. }, )) => { if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) { - let parent = self.tcx.hir().parent_id(pat.hir_id); primary_span = pat.span; secondary_span = pat.span; - match self.tcx.hir().find(parent) { + match self.tcx.hir().find_parent(pat.hir_id) { Some(hir::Node::Local(hir::Local { ty: Some(ty), .. })) => { primary_span = ty.span; post_message = " type"; @@ -857,7 +856,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }?; - match hir.find(hir.parent_id(expr.hir_id))? { + match hir.find_parent(expr.hir_id)? { Node::ExprField(field) => { if field.ident.name == local.name && field.is_shorthand { return Some(local.name); @@ -1040,7 +1039,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Assign(..), .. - })) = self.tcx.hir().find(self.tcx.hir().parent_id(expr.hir_id)) + })) = self.tcx.hir().find_parent(expr.hir_id) { if mutability.is_mut() { // Suppressing this diagnostic, we'll properly print it in `check_expr_assign` @@ -1267,9 +1266,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut sugg = vec![]; - if let Some(hir::Node::ExprField(field)) = - self.tcx.hir().find(self.tcx.hir().parent_id(expr.hir_id)) - { + if let Some(hir::Node::ExprField(field)) = self.tcx.hir().find_parent(expr.hir_id) { // `expr` is a literal field for a struct, only suggest if appropriate if field.is_shorthand { // This is a field literal diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7b66422cce67..631749fcc0fa 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1083,7 +1083,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Do not suggest `if let x = y` as `==` is way more likely to be the intention. let hir = self.tcx.hir(); if let hir::Node::Expr(hir::Expr { kind: ExprKind::If { .. }, .. }) = - hir.get(hir.parent_id(hir.parent_id(expr.hir_id))) + hir.get_parent(hir.parent_id(expr.hir_id)) { err.span_suggestion_verbose( expr.span.shrink_to_lo(), @@ -2462,7 +2462,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(field.span, "method, not a field"); let expr_is_call = if let hir::Node::Expr(hir::Expr { kind: ExprKind::Call(callee, _args), .. }) = - self.tcx.hir().get(self.tcx.hir().parent_id(expr.hir_id)) + self.tcx.hir().get_parent(expr.hir_id) { expr.hir_id == callee.hir_id } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index a452dcc5014e..634688de01a6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1435,9 +1435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(in super::super) fn expr_in_place(&self, mut expr_id: hir::HirId) -> bool { let mut contained_in_place = false; - while let hir::Node::Expr(parent_expr) = - self.tcx.hir().get(self.tcx.hir().parent_id(expr_id)) - { + while let hir::Node::Expr(parent_expr) = self.tcx.hir().get_parent(expr_id) { match &parent_expr.kind { hir::ExprKind::Assign(lhs, ..) | hir::ExprKind::AssignOp(_, lhs, ..) => { if lhs.hir_id == expr_id { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index fbb4da153b88..3de0f7c6f650 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1803,7 +1803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id: call_hir_id, span: call_span, .. - }) = hir.get(hir.parent_id(expr.hir_id)) + }) = hir.get_parent(expr.hir_id) && callee.hir_id == expr.hir_id { if self.closure_span_overlaps_error(error, *call_span) { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index ccee9b2554ce..dd9ea59eefc0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1451,7 +1451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let filename = tcx.sess.source_map().span_to_filename(span); let parent_node = - self.tcx.hir().get(self.tcx.hir().parent_id(hir_id)); + self.tcx.hir().get_parent(hir_id); let msg = format!( "you must specify a type for this binding, like `{}`", concrete_type, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index ff3b347ee018..0143901f2d7a 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -936,7 +936,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { res.descr(), ), ); - match self.tcx.hir().get(self.tcx.hir().parent_id(pat.hir_id)) { + match self.tcx.hir().get_parent(pat.hir_id) { hir::Node::PatField(..) => { e.span_suggestion_verbose( ident.span.shrink_to_hi(), diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 1ebfde16df9a..5b02956a106c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -585,45 +585,42 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir::StmtKind::Local(local) = &stmt.kind else { continue; }; local.pat.walk(&mut find_compatible_candidates); } - match hir.find(hir.parent_id(blk.hir_id)) { - Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => { - match hir.find(hir.parent_id(*hir_id)) { - Some(hir::Node::Arm(hir::Arm { pat, .. })) => { - pat.walk(&mut find_compatible_candidates); - } - Some( - hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. }) - | hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(_, body), - .. - }) - | hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)), - .. - }) - | hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Closure(hir::Closure { body, .. }), - .. - }), - ) => { - for param in hir.body(*body).params { - param.pat.walk(&mut find_compatible_candidates); - } - } - Some(hir::Node::Expr(hir::Expr { - kind: - hir::ExprKind::If( - hir::Expr { kind: hir::ExprKind::Let(let_), .. }, - then_block, - _, - ), - .. - })) if then_block.hir_id == *hir_id => { - let_.pat.walk(&mut find_compatible_candidates); - } - _ => {} + match hir.find_parent(blk.hir_id) { + Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => match hir.find_parent(*hir_id) { + Some(hir::Node::Arm(hir::Arm { pat, .. })) => { + pat.walk(&mut find_compatible_candidates); } - } + Some( + hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. }) + | hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(_, body), .. + }) + | hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Closure(hir::Closure { body, .. }), + .. + }), + ) => { + for param in hir.body(*body).params { + param.pat.walk(&mut find_compatible_candidates); + } + } + Some(hir::Node::Expr(hir::Expr { + kind: + hir::ExprKind::If( + hir::Expr { kind: hir::ExprKind::Let(let_), .. }, + then_block, + _, + ), + .. + })) if then_block.hir_id == *hir_id => { + let_.pat.walk(&mut find_compatible_candidates); + } + _ => {} + }, _ => {} } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3c2f2e9417a5..d58168ff3772 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1526,7 +1526,7 @@ impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_field_def(&mut self, cx: &LateContext<'_>, field: &hir::FieldDef<'_>) { let map = cx.tcx.hir(); - if matches!(map.get(map.parent_id(field.hir_id)), Node::Variant(_)) { + if matches!(map.get_parent(field.hir_id), Node::Variant(_)) { return; } self.perform_lint(cx, "field", field.def_id, field.vis_span, false); diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 96084a50984e..48902cd05695 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind { TyKind::Path(QPath::Resolved(_, path)) => { if lint_ty_kind_usage(cx, &path.res) { let hir = cx.tcx.hir(); - let span = match hir.find(hir.parent_id(ty.hir_id)) { + let span = match hir.find_parent(ty.hir_id) { Some(Node::Pat(Pat { kind: PatKind::Path(qpath) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index a4182c121ed0..f37d6e9a63d4 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -444,7 +444,7 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { if let PatKind::Binding(_, hid, ident, _) = p.kind { - if let hir::Node::PatField(field) = cx.tcx.hir().get(cx.tcx.hir().parent_id(hid)) { + if let hir::Node::PatField(field) = cx.tcx.hir().get_parent(hid) { if !field.is_shorthand { // Only check if a new name has been introduced, to avoid warning // on both the struct definition and this pattern. diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 9b67ab38f909..fa415243ba06 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -129,8 +129,7 @@ fn lint_overflowing_range_endpoint<'tcx>( // which are represented as `ExprKind::Struct`. let par_id = cx.tcx.hir().parent_id(expr.hir_id); let Node::ExprField(field) = cx.tcx.hir().get(par_id) else { return false }; - let field_par_id = cx.tcx.hir().parent_id(field.hir_id); - let Node::Expr(struct_expr) = cx.tcx.hir().get(field_par_id) else { return false }; + let Node::Expr(struct_expr) = cx.tcx.hir().get_parent(field.hir_id) else { return false }; if !is_range_literal(struct_expr) { return false; }; diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 65a49a5fe85e..883554f959cc 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -246,7 +246,7 @@ impl<'hir> Map<'hir> { }, Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { - let ctor_of = match self.find(self.parent_id(hir_id)) { + let ctor_of = match self.find_parent(hir_id) { Some(Node::Item(..)) => def::CtorOf::Struct, Some(Node::Variant(..)) => def::CtorOf::Variant, _ => unreachable!(), @@ -257,7 +257,7 @@ impl<'hir> Map<'hir> { } } Node::AnonConst(_) => { - let inline = match self.find(self.parent_id(hir_id)) { + let inline = match self.find_parent(hir_id) { Some(Node::Expr(&Expr { kind: ExprKind::ConstBlock(ref anon_const), .. })) if anon_const.hir_id == hir_id => true, @@ -317,6 +317,14 @@ impl<'hir> Map<'hir> { .unwrap_or_else(|| bug!("No parent for node {:?}", self.node_to_string(hir_id))) } + pub fn get_parent(self, hir_id: HirId) -> Node<'hir> { + self.get(self.parent_id(hir_id)) + } + + pub fn find_parent(self, hir_id: HirId) -> Option> { + self.find(self.opt_parent_id(hir_id)?) + } + /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(self, id: HirId) -> Option> { if id.local_id == ItemLocalId::from_u32(0) { @@ -664,7 +672,7 @@ impl<'hir> Map<'hir> { /// Checks if the node is left-hand side of an assignment. pub fn is_lhs(self, id: HirId) -> bool { - match self.find(self.parent_id(id)) { + match self.find_parent(id) { Some(Node::Expr(expr)) => match expr.kind { ExprKind::Assign(lhs, _rhs, _span) => lhs.hir_id == id, _ => false, @@ -892,7 +900,7 @@ impl<'hir> Map<'hir> { Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident), // A `Ctor` doesn't have an identifier itself, but its parent // struct/variant does. Compare with `hir::Map::opt_span`. - Node::Ctor(..) => match self.find(self.parent_id(id))? { + Node::Ctor(..) => match self.find_parent(id)? { Node::Item(item) => Some(item.ident), Node::Variant(variant) => Some(variant.ident), _ => unreachable!(), @@ -1093,7 +1101,7 @@ impl<'hir> Map<'hir> { /// Returns the HirId of `N` in `struct Foo` when /// called with the HirId for the `{ ... }` anon const pub fn opt_const_param_default_param_def_id(self, anon_const: HirId) -> Option { - match self.get(self.parent_id(anon_const)) { + match self.get_parent(anon_const) { Node::GenericParam(GenericParam { def_id: param_id, kind: GenericParamKind::Const { .. }, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index e1aa7fea441c..50554cf9a82c 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -457,7 +457,7 @@ impl<'tcx> TyCtxt<'tcx> { .def_id .as_local() .map(|id| hir.local_def_id_to_hir_id(id)) - .and_then(|id| self.hir().find(self.hir().parent_id(id))) + .and_then(|id| self.hir().find_parent(id)) .as_ref() .and_then(|node| node.generics()) { 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 bf5e06268e96..8c2c18287749 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -838,8 +838,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let hir = self.tcx.hir(); let hir_id = hir.local_def_id_to_hir_id(def_id.as_local()?); - let parent_node = hir.parent_id(hir_id); - match hir.find(parent_node) { + match hir.find_parent(hir_id) { Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => { get_name(err, &local.pat.kind) } @@ -3287,8 +3286,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind && let hir::Path { res: hir::def::Res::Local(hir_id), .. } = path && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(*hir_id) - && let parent_hir_id = self.tcx.hir().parent_id(binding.hir_id) - && let Some(parent) = self.tcx.hir().find(parent_hir_id) + && let Some(parent) = self.tcx.hir().find_parent(binding.hir_id) { // We've reached the root of the method call chain... if let hir::Node::Local(local) = parent diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs index 58b7b9829a10..dfb43893326e 100644 --- a/src/tools/clippy/clippy_lints/src/escape.rs +++ b/src/tools/clippy/clippy_lints/src/escape.rs @@ -131,7 +131,7 @@ fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { _ => return false, } - matches!(map.find(map.parent_id(id)), Some(Node::Param(_))) + matches!(map.find_parent(id), Some(Node::Param(_))) } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { @@ -157,7 +157,7 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { if is_argument(*map, cmt.hir_id) { // Skip closure arguments let parent_id = map.parent_id(cmt.hir_id); - if let Some(Node::Expr(..)) = map.find(map.parent_id(parent_id)) { + if let Some(Node::Expr(..)) = map.find_parent(parent_id) { return; } diff --git a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs index 494fde395e93..38f41d077c16 100644 --- a/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs +++ b/src/tools/clippy/clippy_lints/src/manual_rem_euclid.rs @@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { && let Some(hir_id) = path_to_local(expr3) && let Some(Node::Pat(_)) = cx.tcx.hir().find(hir_id) { // Apply only to params or locals with annotated types - match cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { + match cx.tcx.hir().find_parent(hir_id) { Some(Node::Param(..)) => (), Some(Node::Local(local)) => { let Some(ty) = local.ty else { return }; diff --git a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs index abe9d231f4aa..065a5c72621c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_single_binding.rs @@ -140,8 +140,8 @@ pub(crate) fn check<'a>(cx: &LateContext<'a>, ex: &Expr<'a>, arms: &[Arm<'_>], e fn opt_parent_assign_span<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option { let map = &cx.tcx.hir(); - if let Some(Node::Expr(parent_arm_expr)) = map.find(map.parent_id(ex.hir_id)) { - return match map.find(map.parent_id(parent_arm_expr.hir_id)) { + if let Some(Node::Expr(parent_arm_expr)) = map.find_parent(ex.hir_id) { + return match map.find_parent(parent_arm_expr.hir_id) { Some(Node::Local(parent_let_expr)) => Some(AssignmentExpr::Local { span: parent_let_expr.span, pat_span: parent_let_expr.pat.span(), @@ -183,8 +183,7 @@ fn sugg_with_curlies<'a>( // If the parent is already an arm, and the body is another match statement, // we need curly braces around suggestion - let parent_node_id = cx.tcx.hir().parent_id(match_expr.hir_id); - if let Node::Arm(arm) = &cx.tcx.hir().get(parent_node_id) { + if let Node::Arm(arm) = &cx.tcx.hir().get_parent(match_expr.hir_id) { if let ExprKind::Match(..) = arm.body.kind { cbrace_end = format!("\n{indent}}}"); // Fix body indent due to the match diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 58c54280a234..1249db5dc479 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -100,7 +100,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index f96a19b27235..870a1c7d88d5 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -299,7 +299,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByRefOrValue { } // Exclude non-inherent impls - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs index ac4f8789a434..dd120599c04e 100644 --- a/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs +++ b/src/tools/clippy/clippy_lints/src/unit_types/unit_arg.rs @@ -21,7 +21,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { return; } let map = &cx.tcx.hir(); - let opt_parent_node = map.find(map.parent_id(expr.hir_id)); + let opt_parent_node = map.find_parent(expr.hir_id); if_chain! { if let Some(hir::Node::Expr(parent_expr)) = opt_parent_node; if is_questionmark_desugar_marked_call(parent_expr); @@ -192,7 +192,7 @@ fn fmt_stmts_and_call( let mut stmts_and_call_snippet = stmts_and_call.join(&format!("{}{}", ";\n", " ".repeat(call_expr_indent))); // expr is not in a block statement or result expression position, wrap in a block - let parent_node = cx.tcx.hir().find(cx.tcx.hir().parent_id(call_expr.hir_id)); + let parent_node = cx.tcx.hir().find_parent(call_expr.hir_id); if !matches!(parent_node, Some(Node::Block(_))) && !matches!(parent_node, Some(Node::Stmt(_))) { let block_indent = call_expr_indent + 4; stmts_and_call_snippet = diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs index 63f4f01b0877..84ec0d0fb1cf 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs @@ -91,7 +91,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps { } // Abort if the method is implementing a trait or of it a trait method. - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { if matches!( item.kind, ItemKind::Impl(Impl { of_trait: Some(_), .. }) | ItemKind::Trait(..) diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs index a177ae507bbe..c86f24cbd378 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/metadata_collector.rs @@ -1058,7 +1058,7 @@ fn get_parent_local<'hir>(cx: &LateContext<'hir>, expr: &'hir hir::Expr<'hir>) - fn get_parent_local_hir_id<'hir>(cx: &LateContext<'hir>, hir_id: hir::HirId) -> Option<&'hir hir::Local<'hir>> { let map = cx.tcx.hir(); - match map.find(map.parent_id(hir_id)) { + match map.find_parent((hir_id)) { Some(hir::Node::Local(local)) => Some(local), Some(hir::Node::Pat(pattern)) => get_parent_local_hir_id(cx, pattern.hir_id), _ => None, diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 63d0938169a8..8290fe9ecb4c 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1287,7 +1287,7 @@ pub fn contains_return(expr: &hir::Expr<'_>) -> bool { /// Gets the parent node, if any. pub fn get_parent_node(tcx: TyCtxt<'_>, id: HirId) -> Option> { - tcx.hir().parent_iter(id).next().map(|(_, node)| node) + tcx.hir().find_parent(id) } /// Gets the parent expression, if any –- this is useful to constrain a lint. @@ -2075,7 +2075,7 @@ pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool { /// } /// ``` pub fn is_trait_impl_item(cx: &LateContext<'_>, hir_id: HirId) -> bool { - if let Some(Node::Item(item)) = cx.tcx.hir().find(cx.tcx.hir().parent_id(hir_id)) { + if let Some(Node::Item(item)) = cx.tcx.hir().find_parent(hir_id) { matches!(item.kind, ItemKind::Impl(hir::Impl { of_trait: Some(_), .. })) } else { false From 7690fe3bc66cae219301368650317936f0d4e3a9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 10 Dec 2022 20:31:01 +0000 Subject: [PATCH 119/223] Simplify some iterator combinators --- .../src/diagnostics/conflict_errors.rs | 23 ++--- .../src/diagnostics/region_errors.rs | 50 +++++----- compiler/rustc_codegen_gcc/src/builder.rs | 2 +- compiler/rustc_codegen_gcc/src/context.rs | 2 +- compiler/rustc_hir_typeck/src/lib.rs | 9 +- .../src/method/prelude2021.rs | 3 +- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 4 +- .../nice_region_error/static_impl_trait.rs | 91 ++++++++----------- compiler/rustc_lint/src/unused.rs | 27 +++--- compiler/rustc_macros/src/symbols/tests.rs | 3 +- compiler/rustc_resolve/src/ident.rs | 9 +- 12 files changed, 91 insertions(+), 135 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 3c3cb8c6b9c2..6d6ad199be35 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -527,26 +527,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // that are *partially* initialized by assigning to a field of an uninitialized // binding. We differentiate between them for more accurate wording here. "isn't fully initialized" - } else if spans - .iter() - .filter(|i| { - // We filter these to avoid misleading wording in cases like the following, - // where `x` has an `init`, but it is in the same place we're looking at: - // ``` - // let x; - // x += 1; - // ``` - !i.contains(span) + } else if !spans.iter().any(|i| { + // We filter these to avoid misleading wording in cases like the following, + // where `x` has an `init`, but it is in the same place we're looking at: + // ``` + // let x; + // x += 1; + // ``` + !i.contains(span) // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs` && !visitor .errors .iter() .map(|(sp, _)| *sp) .any(|sp| span < sp && !sp.contains(span)) - }) - .count() - == 0 - { + }) { show_assign_sugg = true; "isn't initialized" } else { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index bcc8afbfd952..631e147ce8c5 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -316,35 +316,29 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // obligation comes from the `impl`. Find that `impl` so that we can point // at it in the suggestion. let trait_did = trait_did.to_def_id(); - match tcx - .hir() - .trait_impls(trait_did) - .iter() - .filter_map(|&impl_did| { - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) if trait_objects.iter().all(|did| { - // FIXME: we should check `self_ty` against the receiver - // type in the `UnifyReceiver` context, but for now, use - // this imperfect proxy. This will fail if there are - // multiple `impl`s for the same trait like - // `impl Foo for Box` and `impl Foo for dyn Bar`. - // In that case, only the first one will get suggestions. - let mut traits = vec![]; - let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); - hir_v.visit_ty(self_ty); - !traits.is_empty() - }) => - { - Some(self_ty) - } - _ => None, + match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + })) if trait_objects.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); + hir_v.visit_ty(self_ty); + !traits.is_empty() + }) => + { + Some(self_ty) } - }) - .next() - { + _ => None, + } + }) { Some(self_ty) => Some((trait_item.ident, self_ty)), _ => None, } diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index effb2de48275..a92242b2615c 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1244,7 +1244,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ) -> RValue<'gcc> { // FIXME(antoyo): remove when having a proper API. let gcc_func = unsafe { std::mem::transmute(func) }; - let call = if self.functions.borrow().values().find(|value| **value == gcc_func).is_some() { + let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { self.function_call(func, args, funclet) } else { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 837708aeb0ea..4424b31c0542 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -253,7 +253,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; - debug_assert!(self.functions.borrow().values().find(|value| **value == function).is_some(), + debug_assert!(self.functions.borrow().values().any(|value| *value == function), "{:?} ({:?}) is not a function", value, value.get_type()); function } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index b06927f9662b..cecf3d3f1e06 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -240,10 +240,8 @@ fn typeck_with_fallback<'tcx>( }), Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. }) | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => { - let operand_ty = asm - .operands - .iter() - .filter_map(|(op, _op_sp)| match op { + let operand_ty = + asm.operands.iter().find_map(|(op, _op_sp)| match op { hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => { @@ -259,8 +257,7 @@ fn typeck_with_fallback<'tcx>( })) } _ => None, - }) - .next(); + }); operand_ty.unwrap_or_else(fallback) } _ => fallback(), diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs index dea14dd93d6a..3d6c2119bea3 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs @@ -341,8 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find an identifier with which this trait was imported (note that `_` doesn't count). let any_id = import_items .iter() - .filter_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None }) - .next(); + .find_map(|item| if item.ident.name != Underscore { Some(item.ident) } else { None }); if let Some(any_id) = any_id { if any_id.name == Empty { // Glob import, so just use its name. diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 1afaae0e0209..2daf1979ee5e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1111,7 +1111,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // a raw pointer !step.self_ty.references_error() && !step.from_unsafe_deref }) - .flat_map(|step| { + .find_map(|step| { let InferOk { value: self_ty, obligations: _ } = self .fcx .probe_instantiate_query_response( @@ -1147,7 +1147,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { }) }) }) - .next() } /// For each type `T` in the step list, this attempts to find a method where diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 71c3803e64fa..b04ef55a994e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -257,9 +257,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx .inherent_impls(adt_def.did()) .iter() - .filter_map(|def_id| self.associated_value(*def_id, item_name)) - .count() - >= 1 + .any(|def_id| self.associated_value(*def_id, item_name).is_some()) } else { false } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9bd2202d2601..58be91bc276a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -309,19 +309,12 @@ pub fn suggest_new_region_bound( let did = item_id.owner_id.to_def_id(); let ty = tcx.mk_opaque(did, ty::InternalSubsts::identity_for_item(tcx, did)); - if let Some(span) = opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { - res: LifetimeName::Static, - ident, - .. - }) => Some(ident.span), - _ => None, - }) - .next() - { + if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg { + GenericBound::Outlives(Lifetime { + res: LifetimeName::Static, ident, .. + }) => Some(ident.span), + _ => None, + }) { if let Some(explicit_static) = &explicit_static { err.span_suggestion_verbose( span, @@ -338,20 +331,14 @@ pub fn suggest_new_region_bound( Applicability::MaybeIncorrect, ); } - } else if opaque - .bounds - .iter() - .filter_map(|arg| match arg { - GenericBound::Outlives(Lifetime { ident, .. }) - if ident.name.to_string() == lifetime_name => - { - Some(ident.span) - } - _ => None, - }) - .next() - .is_some() - { + } else if opaque.bounds.iter().any(|arg| match arg { + GenericBound::Outlives(Lifetime { ident, .. }) + if ident.name.to_string() == lifetime_name => + { + true + } + _ => false, + }) { } else { err.span_suggestion_verbose( fn_return.span.shrink_to_hi(), @@ -428,35 +415,29 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // obligation comes from the `impl`. Find that `impl` so that we can point // at it in the suggestion. let trait_did = trait_did.to_def_id(); - match tcx - .hir() - .trait_impls(trait_did) - .iter() - .filter_map(|&impl_did| { - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) if trait_objects.iter().all(|did| { - // FIXME: we should check `self_ty` against the receiver - // type in the `UnifyReceiver` context, but for now, use - // this imperfect proxy. This will fail if there are - // multiple `impl`s for the same trait like - // `impl Foo for Box` and `impl Foo for dyn Bar`. - // In that case, only the first one will get suggestions. - let mut traits = vec![]; - let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); - hir_v.visit_ty(self_ty); - !traits.is_empty() - }) => - { - Some(self_ty) - } - _ => None, + match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { + match tcx.hir().get_if_local(impl_did.to_def_id()) { + Some(Node::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + })) if trait_objects.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); + hir_v.visit_ty(self_ty); + !traits.is_empty() + }) => + { + Some(self_ty) } - }) - .next() - { + _ => None, + } + }) { Some(self_ty) => Some((trait_item.ident, self_ty)), _ => None, } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index a7a5234049fe..bf1f150fc3b4 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -256,7 +256,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned(), ) - .filter_map(|obligation| { + .find_map(|obligation| { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait( ref poly_trait_predicate, @@ -270,22 +270,17 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } }) .map(|inner| MustUsePath::Opaque(Box::new(inner))) - .next() } - ty::Dynamic(binders, _, _) => binders - .iter() - .filter_map(|predicate| { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = - predicate.skip_binder() - { - let def_id = trait_ref.def_id; - is_def_must_use(cx, def_id, span) - } else { - None - } - .map(|inner| MustUsePath::TraitObject(Box::new(inner))) - }) - .next(), + ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() + { + let def_id = trait_ref.def_id; + is_def_must_use(cx, def_id, span) + } else { + None + } + .map(|inner| MustUsePath::TraitObject(Box::new(inner))) + }), ty::Tuple(tys) => { let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind { debug_assert_eq!(elem_exprs.len(), tys.len()); diff --git a/compiler/rustc_macros/src/symbols/tests.rs b/compiler/rustc_macros/src/symbols/tests.rs index 842d2a977189..bd0c08a53c4f 100644 --- a/compiler/rustc_macros/src/symbols/tests.rs +++ b/compiler/rustc_macros/src/symbols/tests.rs @@ -16,14 +16,13 @@ fn test_symbols() { let m: &syn::ItemMacro = file .items .iter() - .filter_map(|i| { + .find_map(|i| { if let syn::Item::Macro(m) = i { if m.mac.path == symbols_path { Some(m) } else { None } } else { None } }) - .next() .expect("did not find `symbols!` macro invocation."); let body_tokens = m.mac.tokens.clone(); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 0c4b35b88335..e41fe325b811 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -820,13 +820,12 @@ impl<'a> Resolver<'a> { // binding if it exists. What we really want here is having two separate scopes in // a module - one for non-globs and one for globs, but until that's done use this // hack to avoid inconsistent resolution ICEs during import validation. - let binding = [resolution.binding, resolution.shadowed_glob] - .into_iter() - .filter_map(|binding| match (binding, ignore_binding) { + let binding = [resolution.binding, resolution.shadowed_glob].into_iter().find_map( + |binding| match (binding, ignore_binding) { (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, _ => binding, - }) - .next(); + }, + ); let Some(binding) = binding else { return Err((Determined, Weak::No)); }; From 2baee88bdb6ebbfda067818f5f4194083c2a77c1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 27 Dec 2022 17:53:29 +0000 Subject: [PATCH 120/223] Address comments --- .../src/diagnostics/conflict_errors.rs | 12 +-- .../src/diagnostics/region_errors.rs | 63 +------------ .../nice_region_error/static_impl_trait.rs | 92 +++++++++---------- compiler/rustc_lint/src/unused.rs | 2 +- 4 files changed, 52 insertions(+), 117 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 6d6ad199be35..50cd13a2ccc8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -535,12 +535,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // x += 1; // ``` !i.contains(span) - // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs` - && !visitor - .errors - .iter() - .map(|(sp, _)| *sp) - .any(|sp| span < sp && !sp.contains(span)) + // We filter these to avoid incorrect main message on `match-cfg-fake-edges.rs` + && !visitor + .errors + .iter() + .map(|(sp, _)| *sp) + .any(|sp| span < sp && !sp.contains(span)) }) { show_assign_sugg = true; "isn't initialized" diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 631e147ce8c5..567a9814fccb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -4,9 +4,9 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; +use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, Item, ItemKind, Node}; use rustc_infer::infer::{ error_reporting::nice_region_error::{ self, find_anon_type, find_param_with_region, suggest_adding_lifetime_params, @@ -291,65 +291,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { outlives_suggestion.add_suggestion(self); } - fn get_impl_ident_and_self_ty_from_trait( - &self, - def_id: DefId, - trait_objects: &FxIndexSet, - ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { - let tcx = self.infcx.tcx; - match tcx.hir().get_if_local(def_id) { - Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) - { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) => Some((impl_item.ident, self_ty)), - _ => None, - } - } - Some(Node::TraitItem(trait_item)) => { - let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did.def_id) { - Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { - // The method being called is defined in the `trait`, but the `'static` - // obligation comes from the `impl`. Find that `impl` so that we can point - // at it in the suggestion. - let trait_did = trait_did.to_def_id(); - match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) if trait_objects.iter().all(|did| { - // FIXME: we should check `self_ty` against the receiver - // type in the `UnifyReceiver` context, but for now, use - // this imperfect proxy. This will fail if there are - // multiple `impl`s for the same trait like - // `impl Foo for Box` and `impl Foo for dyn Bar`. - // In that case, only the first one will get suggestions. - let mut traits = vec![]; - let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); - hir_v.visit_ty(self_ty); - !traits.is_empty() - }) => - { - Some(self_ty) - } - _ => None, - } - }) { - Some(self_ty) => Some((trait_item.ident, self_ty)), - _ => None, - } - } - _ => None, - } - } - _ => None, - } - } - /// Report an error because the universal region `fr` was required to outlive /// `outlived_fr` but it is not known to do so. For example: /// @@ -844,7 +785,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { visitor.visit_ty(param.param_ty); let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &visitor.0) else {return}; + NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; }; self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty); } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 58be91bc276a..d9cdfa9dd4fc 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -239,7 +239,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut v = TraitObjectVisitor(FxIndexSet::default()); v.visit_ty(param.param_ty); if let Some((ident, self_ty)) = - self.get_impl_ident_and_self_ty_from_trait(item_def_id, &v.0) + NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, item_def_id, &v.0) && self.suggest_constrain_dyn_trait_in_impl(&mut err, &v.0, ident, self_ty) { override_error_code = Some(ident.name); @@ -390,60 +390,54 @@ pub fn suggest_new_region_bound( } impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { - fn get_impl_ident_and_self_ty_from_trait( - &self, + pub fn get_impl_ident_and_self_ty_from_trait( + tcx: TyCtxt<'tcx>, def_id: DefId, trait_objects: &FxIndexSet, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { - let tcx = self.tcx(); - match tcx.hir().get_if_local(def_id) { - Some(Node::ImplItem(impl_item)) => { - match tcx.hir().find_by_def_id(tcx.hir().get_parent_item(impl_item.hir_id()).def_id) + match tcx.hir().get_if_local(def_id)? { + Node::ImplItem(impl_item) => { + let impl_did = tcx.hir().get_parent_item(impl_item.hir_id()); + if let hir::OwnerNode::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + }) = tcx.hir().owner(impl_did) { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) => Some((impl_item.ident, self_ty)), - _ => None, + Some((impl_item.ident, self_ty)) + } else { + None } } - Some(Node::TraitItem(trait_item)) => { - let trait_did = tcx.hir().get_parent_item(trait_item.hir_id()); - match tcx.hir().find_by_def_id(trait_did.def_id) { - Some(Node::Item(Item { kind: ItemKind::Trait(..), .. })) => { - // The method being called is defined in the `trait`, but the `'static` - // obligation comes from the `impl`. Find that `impl` so that we can point - // at it in the suggestion. - let trait_did = trait_did.to_def_id(); - match tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { - match tcx.hir().get_if_local(impl_did.to_def_id()) { - Some(Node::Item(Item { - kind: ItemKind::Impl(hir::Impl { self_ty, .. }), - .. - })) if trait_objects.iter().all(|did| { - // FIXME: we should check `self_ty` against the receiver - // type in the `UnifyReceiver` context, but for now, use - // this imperfect proxy. This will fail if there are - // multiple `impl`s for the same trait like - // `impl Foo for Box` and `impl Foo for dyn Bar`. - // In that case, only the first one will get suggestions. - let mut traits = vec![]; - let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); - hir_v.visit_ty(self_ty); - !traits.is_empty() - }) => - { - Some(self_ty) - } - _ => None, - } - }) { - Some(self_ty) => Some((trait_item.ident, self_ty)), - _ => None, - } + Node::TraitItem(trait_item) => { + let trait_id = tcx.hir().get_parent_item(trait_item.hir_id()); + debug_assert_eq!(tcx.def_kind(trait_id.def_id), hir::def::DefKind::Trait); + // The method being called is defined in the `trait`, but the `'static` + // obligation comes from the `impl`. Find that `impl` so that we can point + // at it in the suggestion. + let trait_did = trait_id.to_def_id(); + tcx.hir().trait_impls(trait_did).iter().find_map(|&impl_did| { + if let Node::Item(Item { + kind: ItemKind::Impl(hir::Impl { self_ty, .. }), + .. + }) = tcx.hir().find_by_def_id(impl_did)? + && trait_objects.iter().all(|did| { + // FIXME: we should check `self_ty` against the receiver + // type in the `UnifyReceiver` context, but for now, use + // this imperfect proxy. This will fail if there are + // multiple `impl`s for the same trait like + // `impl Foo for Box` and `impl Foo for dyn Bar`. + // In that case, only the first one will get suggestions. + let mut traits = vec![]; + let mut hir_v = HirTraitObjectVisitor(&mut traits, *did); + hir_v.visit_ty(self_ty); + !traits.is_empty() + }) + { + Some((trait_item.ident, *self_ty)) + } else { + None } - _ => None, - } + }) } _ => None, } @@ -474,7 +468,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { // Get the `Ident` of the method being called and the corresponding `impl` (to point at // `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called). - let Some((ident, self_ty)) = self.get_impl_ident_and_self_ty_from_trait(instance.def_id(), &v.0) else { + let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &v.0) else { return false; }; diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index bf1f150fc3b4..525079681ca5 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -276,10 +276,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { { let def_id = trait_ref.def_id; is_def_must_use(cx, def_id, span) + .map(|inner| MustUsePath::TraitObject(Box::new(inner))) } else { None } - .map(|inner| MustUsePath::TraitObject(Box::new(inner))) }), ty::Tuple(tys) => { let elem_exprs = if let hir::ExprKind::Tup(elem_exprs) = expr.kind { From b25da9ce6dd28d13c85911e0630d019403b7f5f3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Nov 2022 23:54:39 +0000 Subject: [PATCH 121/223] layout_of: `T: Thin` implies `sizeof(&T) == sizeof(usize)` --- compiler/rustc_ty_utils/src/layout.rs | 36 ++++++++++++++----- .../ui/layout/thin-meta-implies-thin-ptr.rs | 11 ++++++ 2 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/layout/thin-meta-implies-thin-ptr.rs diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index c8c6acaa4539..6aa016133ca5 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -155,17 +155,37 @@ fn layout_of_uncached<'tcx>( } let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = match unsized_part.kind() { - ty::Foreign(..) => { + + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata_ty = tcx.normalize_erasing_regions( + param_env, + tcx.mk_projection(metadata_def_id, [pointee]), + ); + let metadata_layout = cx.layout_of(metadata_ty)?; + // If the metadata is a 1-zst, then the pointer is thin. + if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); } - ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), - ty::Dynamic(..) => { - let mut vtable = scalar_unit(Pointer); - vtable.valid_range_mut().start = 1; - vtable + + let Abi::Scalar(metadata) = metadata_layout.abi else { + return Err(LayoutError::Unknown(unsized_part)); + }; + metadata + } else { + match unsized_part.kind() { + ty::Foreign(..) => { + return Ok(tcx.intern_layout(LayoutS::scalar(cx, data_ptr))); + } + ty::Slice(_) | ty::Str => scalar_unit(Int(dl.ptr_sized_integer(), false)), + ty::Dynamic(..) => { + let mut vtable = scalar_unit(Pointer); + vtable.valid_range_mut().start = 1; + vtable + } + _ => { + return Err(LayoutError::Unknown(unsized_part)); + } } - _ => return Err(LayoutError::Unknown(unsized_part)), }; // Effectively a (ptr, meta) tuple. diff --git a/src/test/ui/layout/thin-meta-implies-thin-ptr.rs b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs new file mode 100644 index 000000000000..972579ea8be0 --- /dev/null +++ b/src/test/ui/layout/thin-meta-implies-thin-ptr.rs @@ -0,0 +1,11 @@ +// check-pass + +#![feature(ptr_metadata)] + +use std::ptr::Thin; + +fn main() {} + +fn foo(t: *const T) -> *const () { + unsafe { std::mem::transmute(t) } +} From 2011316e596c19a8b5ae8cc00102667c2cdb1ef7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 13 Nov 2022 21:49:54 +0000 Subject: [PATCH 122/223] Mirror metadata changes in layout sanity check --- compiler/rustc_middle/src/ty/layout.rs | 52 ++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 9e0ca44d0981..112f15c6f9e6 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -670,13 +670,24 @@ where }); } - match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { - ty::Slice(_) | ty::Str => TyMaybeWithLayout::Ty(tcx.types.usize), - ty::Dynamic(_, _, ty::Dyn) => { - TyMaybeWithLayout::Ty(tcx.mk_imm_ref( + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { + let metadata = tcx.normalize_erasing_regions( + cx.param_env(), + tcx.mk_projection(metadata_def_id, [pointee]), + ); + + // Map `Metadata = DynMetadata` back to a vtable, since it + // offers better information than `std::ptr::metadata::VTable`, + // and we rely on this layout information to trigger a panic in + // `std::mem::uninitialized::<&dyn Trait>()`, for example. + if let ty::Adt(def, substs) = metadata.kind() + && Some(def.did()) == tcx.lang_items().dyn_metadata() + && substs.type_at(0).is_trait() + { + tcx.mk_imm_ref( tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3), - )) + ) /* FIXME: use actual fn pointers Warning: naively computing the number of entries in the vtable by counting the methods on the trait + methods on @@ -690,9 +701,36 @@ where tcx.mk_array(Option), ]) */ + } else { + metadata } - _ => bug!("TyAndLayout::field({:?}): not applicable", this), - } + } else { + match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { + ty::Slice(_) | ty::Str => tcx.types.usize, + ty::Dynamic(_, _, ty::Dyn) => { + tcx.mk_imm_ref( + tcx.lifetimes.re_static, + tcx.mk_array(tcx.types.usize, 3), + ) + /* FIXME: use actual fn pointers + Warning: naively computing the number of entries in the + vtable by counting the methods on the trait + methods on + all parent traits does not work, because some methods can + be not object safe and thus excluded from the vtable. + Increase this counter if you tried to implement this but + failed to do it without duplicating a lot of code from + other places in the compiler: 2 + tcx.mk_tup(&[ + tcx.mk_array(tcx.types.usize, 3), + tcx.mk_array(Option), + ]) + */ + } + _ => bug!("TyAndLayout::field({:?}): not applicable", this), + } + }; + + TyMaybeWithLayout::Ty(metadata) } // Arrays and slices. From a5d39cf290d9762d982b6930f10fb4dd34119c3f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Jan 2023 01:02:52 +0000 Subject: [PATCH 123/223] review comment: Deduplicate dyn ty_and_layout_field code --- compiler/rustc_middle/src/ty/layout.rs | 55 +++++++++----------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 112f15c6f9e6..00f53afd6632 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -670,6 +670,23 @@ where }); } + let mk_dyn_vtable = || { + tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.mk_array(tcx.types.usize, 3)) + /* FIXME: use actual fn pointers + Warning: naively computing the number of entries in the + vtable by counting the methods on the trait + methods on + all parent traits does not work, because some methods can + be not object safe and thus excluded from the vtable. + Increase this counter if you tried to implement this but + failed to do it without duplicating a lot of code from + other places in the compiler: 2 + tcx.mk_tup(&[ + tcx.mk_array(tcx.types.usize, 3), + tcx.mk_array(Option), + ]) + */ + }; + let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { let metadata = tcx.normalize_erasing_regions( cx.param_env(), @@ -684,48 +701,14 @@ where && Some(def.did()) == tcx.lang_items().dyn_metadata() && substs.type_at(0).is_trait() { - tcx.mk_imm_ref( - tcx.lifetimes.re_static, - tcx.mk_array(tcx.types.usize, 3), - ) - /* FIXME: use actual fn pointers - Warning: naively computing the number of entries in the - vtable by counting the methods on the trait + methods on - all parent traits does not work, because some methods can - be not object safe and thus excluded from the vtable. - Increase this counter if you tried to implement this but - failed to do it without duplicating a lot of code from - other places in the compiler: 2 - tcx.mk_tup(&[ - tcx.mk_array(tcx.types.usize, 3), - tcx.mk_array(Option), - ]) - */ + mk_dyn_vtable() } else { metadata } } else { match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, - ty::Dynamic(_, _, ty::Dyn) => { - tcx.mk_imm_ref( - tcx.lifetimes.re_static, - tcx.mk_array(tcx.types.usize, 3), - ) - /* FIXME: use actual fn pointers - Warning: naively computing the number of entries in the - vtable by counting the methods on the trait + methods on - all parent traits does not work, because some methods can - be not object safe and thus excluded from the vtable. - Increase this counter if you tried to implement this but - failed to do it without duplicating a lot of code from - other places in the compiler: 2 - tcx.mk_tup(&[ - tcx.mk_array(tcx.types.usize, 3), - tcx.mk_array(Option), - ]) - */ - } + ty::Dynamic(_, _, ty::Dyn) => mk_dyn_vtable(), _ => bug!("TyAndLayout::field({:?}): not applicable", this), } }; From f98adb32f543d710e6af1941e5373d397b476d6b Mon Sep 17 00:00:00 2001 From: CarsonV Date: Tue, 3 Jan 2023 20:12:09 -0600 Subject: [PATCH 124/223] Enable query_impl doctests --- compiler/rustc_query_impl/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml index b2111a1262a3..46e77626479c 100644 --- a/compiler/rustc_query_impl/Cargo.toml +++ b/compiler/rustc_query_impl/Cargo.toml @@ -4,7 +4,7 @@ version = "0.0.0" edition = "2021" [lib] -doctest = false + [dependencies] measureme = "10.0.0" From 49111eced698e7df62756af364f799609cae3aa7 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 3 Jan 2023 19:46:40 -0700 Subject: [PATCH 125/223] rustdoc: fix buggy JS check for absolute URL The old code did the wrong thing when faced with a crate named "http". --- src/librustdoc/html/static/js/main.js | 2 +- src/test/rustdoc-gui/implementors.goml | 6 ++++++ src/test/rustdoc-gui/search-filter.goml | 2 ++ src/test/rustdoc-gui/sidebar-source-code.goml | 2 +- src/test/rustdoc-gui/source-code-page.goml | 2 +- src/test/rustdoc-gui/src/lib2/Cargo.lock | 8 ++++++++ src/test/rustdoc-gui/src/lib2/Cargo.toml | 1 + src/test/rustdoc-gui/src/lib2/http/Cargo.toml | 7 +++++++ src/test/rustdoc-gui/src/lib2/http/lib.rs | 1 + src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml | 3 +++ src/test/rustdoc-gui/src/lib2/implementors/lib.rs | 2 ++ 11 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc-gui/src/lib2/http/Cargo.toml create mode 100644 src/test/rustdoc-gui/src/lib2/http/lib.rs diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 60e4e7492240..d47b09531798 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -563,7 +563,7 @@ function loadCss(cssUrl) { onEachLazy(code.getElementsByTagName("a"), elem => { const href = elem.getAttribute("href"); - if (href && href.indexOf("http") !== 0) { + if (href && !/^(?:[a-z+]+:)?\/\//.test(href)) { elem.setAttribute("href", window.rootPath + href); } }); diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index 4999283dc8b9..997c0ed8f017 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -33,3 +33,9 @@ goto: "file://" + |DOC_PATH| + "/lib2/trait.TraitToReexport.html" assert-count: ("#implementors-list .impl", 1) goto: "file://" + |DOC_PATH| + "/implementors/trait.TraitToReexport.html" assert-count: ("#implementors-list .impl", 1) + +// Now check that the link is properly rewritten for a crate called `http`. +// An older version of rustdoc had a buggy check for absolute links. +goto: "file://" + |DOC_PATH| + "/http/trait.HttpTrait.html" +assert-count: ("#implementors-list .impl", 1) +assert-attribute: ("#implementors-list .impl a.trait", {"href": "../http/trait.HttpTrait.html"}) diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml index e556da0c54eb..5bc6e87d6d24 100644 --- a/src/test/rustdoc-gui/search-filter.goml +++ b/src/test/rustdoc-gui/search-filter.goml @@ -15,6 +15,7 @@ click: "#crate-search" press-key: "ArrowDown" press-key: "ArrowDown" press-key: "ArrowDown" +press-key: "ArrowDown" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#search-tabs" @@ -39,6 +40,7 @@ click: "#crate-search" press-key: "ArrowUp" press-key: "ArrowUp" press-key: "ArrowUp" +press-key: "ArrowUp" press-key: "Enter" // Waiting for the search results to appear... wait-for: "#search-tabs" diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index d5f57ed6102c..6bc07fbae04d 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -73,7 +73,7 @@ assert: "//*[@class='dir-entry' and @open]/*[text()='sub_mod']" // Only "another_folder" should be "open" in "lib2". assert: "//*[@class='dir-entry' and not(@open)]/*[text()='another_mod']" // All other trees should be collapsed. -assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 7) +assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@open)]", 8) // We now switch to mobile mode. size: (600, 600) diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index aa7921969602..e0397890519b 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -102,7 +102,7 @@ assert: ".source-sidebar-expanded" // We check that the first entry of the sidebar is collapsed assert-property: ("#source-sidebar details:first-of-type", {"open": "false"}) -assert-text: ("#source-sidebar details:first-of-type > summary", "huge_logo") +assert-text: ("#source-sidebar details:first-of-type > summary", "http") // We now click on it. click: "#source-sidebar details:first-of-type > summary" assert-property: ("#source-sidebar details:first-of-type", {"open": "true"}) diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.lock b/src/test/rustdoc-gui/src/lib2/Cargo.lock index a5873ceb3256..425a3ae7e5c9 100644 --- a/src/test/rustdoc-gui/src/lib2/Cargo.lock +++ b/src/test/rustdoc-gui/src/lib2/Cargo.lock @@ -2,13 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "http" +version = "0.1.0" + [[package]] name = "implementors" version = "0.1.0" +dependencies = [ + "http", +] [[package]] name = "lib2" version = "0.1.0" dependencies = [ + "http", "implementors", ] diff --git a/src/test/rustdoc-gui/src/lib2/Cargo.toml b/src/test/rustdoc-gui/src/lib2/Cargo.toml index 2e37f3f667a0..8bca77ff834d 100644 --- a/src/test/rustdoc-gui/src/lib2/Cargo.toml +++ b/src/test/rustdoc-gui/src/lib2/Cargo.toml @@ -8,3 +8,4 @@ path = "lib.rs" [dependencies] implementors = { path = "./implementors" } +http = { path = "./http" } diff --git a/src/test/rustdoc-gui/src/lib2/http/Cargo.toml b/src/test/rustdoc-gui/src/lib2/http/Cargo.toml new file mode 100644 index 000000000000..fa719efa5263 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/http/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "http" +version = "0.1.0" +edition = "2018" + +[lib] +path = "lib.rs" diff --git a/src/test/rustdoc-gui/src/lib2/http/lib.rs b/src/test/rustdoc-gui/src/lib2/http/lib.rs new file mode 100644 index 000000000000..204e07494275 --- /dev/null +++ b/src/test/rustdoc-gui/src/lib2/http/lib.rs @@ -0,0 +1 @@ +pub trait HttpTrait {} diff --git a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml index 7ef1052c49fd..9dafc43df5f8 100644 --- a/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml +++ b/src/test/rustdoc-gui/src/lib2/implementors/Cargo.toml @@ -5,3 +5,6 @@ edition = "2018" [lib] path = "lib.rs" + +[dependencies] +http = { path = "../http/" } diff --git a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs index 1620e8422919..2842ac50dc1e 100644 --- a/src/test/rustdoc-gui/src/lib2/implementors/lib.rs +++ b/src/test/rustdoc-gui/src/lib2/implementors/lib.rs @@ -10,6 +10,8 @@ impl Whatever for Struct { type Foo = u8; } +impl http::HttpTrait for Struct {} + mod traits { pub trait TraitToReexport { fn method() {} From 2399df288ef5af538a331a974b037b889be5cfd2 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Tue, 3 Jan 2023 20:38:07 -0800 Subject: [PATCH 126/223] Add test case to click popover child link --- src/test/rustdoc-gui/help-page.goml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml index 80203901ed3c..050cf325bb82 100644 --- a/src/test/rustdoc-gui/help-page.goml +++ b/src/test/rustdoc-gui/help-page.goml @@ -61,3 +61,11 @@ click: "#help-button > a" assert-css: ("#help", {"display": "none"}) compare-elements-property-false: (".sub", "#help", ["offsetWidth"]) compare-elements-position-false: (".sub", "#help", ("x")) + +// This test ensures that the "the rustdoc book" anchor link within the help popover works. +goto: "file://" + |DOC_PATH| + "/test_docs/index.html" +size: (1000, 1000) // Popover only appears when the screen width is >700px. +assert-false: "#help" +click: "#help-button > a" +click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']" +assert-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"} From 9792c9affb55e44bd93957c166a971007c66b5a2 Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Tue, 3 Jan 2023 23:44:35 -0800 Subject: [PATCH 127/223] Add hardcoded wait time for external navigation to load --- src/test/rustdoc-gui/help-page.goml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml index 050cf325bb82..83f2556fd8f2 100644 --- a/src/test/rustdoc-gui/help-page.goml +++ b/src/test/rustdoc-gui/help-page.goml @@ -68,4 +68,5 @@ size: (1000, 1000) // Popover only appears when the screen width is >700px. assert-false: "#help" click: "#help-button > a" click: ".popover a[href='https://doc.rust-lang.org/rustdoc/']" +wait-for: 2000 assert-document-property: {"URL": "https://doc.rust-lang.org/rustdoc/"} From 77051167083b58c4cd59c658197bcfe6476a7fa5 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 4 Jan 2023 13:37:38 +0000 Subject: [PATCH 128/223] Fix each_linked_rlib when the current crate has 0 crate types --- compiler/rustc_codegen_ssa/src/back/link.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 71589e9993b7..e7df9cc695a4 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -230,6 +230,9 @@ pub fn each_linked_rlib( }); } } + if info.dependency_formats.is_empty() { + return Err(errors::LinkRlibError::MissingFormat); + } &info.dependency_formats[0].1 } else { let fmts = info From ac4426c093b5e7a457e0e32cc6ea2d3fb99c3148 Mon Sep 17 00:00:00 2001 From: Giacomo Pasini Date: Sat, 31 Dec 2022 13:45:22 +0100 Subject: [PATCH 129/223] Merge borrowck permission checks Merge `check_access_permission` and `check_if_reassignment_to_immutable_state`. The goal of this commit is twofold: First, we simplify the codebase by removing duplicate logic. Second, we avoid duplicate reporting of illegal reassignment errors by reusing the exiting de-duplicating logic of access_place. --- compiler/rustc_borrowck/src/lib.rs | 48 +++++++----------------------- 1 file changed, 11 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index ae1bea008b6c..278ffed07477 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -863,7 +863,6 @@ enum WriteKind { /// local place can be mutated. // // FIXME: @nikomatsakis suggested that this flag could be removed with the following modifications: -// - Merge `check_access_permissions()` and `check_if_reassignment_to_immutable_state()`. // - Split `is_mutable()` into `is_assignable()` (can be directly assigned) and // `is_declared_mutable()`. // - Take flow state into consideration in `is_assignable()` for local variables. @@ -1132,20 +1131,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Write of P[i] or *P requires P init'd. self.check_if_assigned_path_is_moved(location, place_span, flow_state); - // Special case: you can assign an immutable local variable - // (e.g., `x = ...`) so long as it has never been initialized - // before (at this point in the flow). - if let Some(local) = place_span.0.as_local() { - if let Mutability::Not = self.body.local_decls[local].mutability { - // check for reassignments to immutable local variables - self.check_if_reassignment_to_immutable_state( - location, local, place_span, flow_state, - ); - return; - } - } - - // Otherwise, use the normal access permission rules. self.access_place( location, place_span, @@ -1554,24 +1539,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn check_if_reassignment_to_immutable_state( - &mut self, - location: Location, - local: Local, - place_span: (Place<'tcx>, Span), - flow_state: &Flows<'cx, 'tcx>, - ) { - debug!("check_if_reassignment_to_immutable_state({:?})", local); - - // Check if any of the initializations of `local` have happened yet: - if let Some(init_index) = self.is_local_ever_initialized(local, flow_state) { - // And, if so, report an error. - let init = &self.move_data.inits[init_index]; - let span = init.span(&self.body); - self.report_illegal_reassignment(location, place_span, span, place_span.0); - } - } - fn check_if_full_path_is_moved( &mut self, location: Location, @@ -2037,12 +2004,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // partial initialization, do not complain about mutability // errors except for actual mutation (as opposed to an attempt // to do a partial initialization). - let previously_initialized = - self.is_local_ever_initialized(place.local, flow_state).is_some(); + let previously_initialized = self.is_local_ever_initialized(place.local, flow_state); // at this point, we have set up the error reporting state. - if previously_initialized { - self.report_mutability_error(place, span, the_place_err, error_access, location); + if let Some(init_index) = previously_initialized { + if let (AccessKind::Mutate, Some(_)) = (error_access, place.as_local()) { + // If this is a mutate access to an immutable local variable with no projections + // report the error as an illegal reassignment + let init = &self.move_data.inits[init_index]; + let assigned_span = init.span(&self.body); + self.report_illegal_reassignment(location, (place, span), assigned_span, place); + } else { + self.report_mutability_error(place, span, the_place_err, error_access, location) + } true } else { false From 0c43b42b0cd1823388418504e84f3c4fec6f33b9 Mon Sep 17 00:00:00 2001 From: Gijs Burghoorn Date: Wed, 4 Jan 2023 16:07:33 +0100 Subject: [PATCH 130/223] Improve include macro documentation --- library/core/src/macros/mod.rs | 62 +++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index cfc1cabe229e..b20e60ad96d1 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1312,28 +1312,52 @@ pub(crate) mod builtin { /* compiler built-in */ }; } - + /// Parses a file as an expression or an item according to the context. /// - /// The file is located relative to the current file (similarly to how - /// modules are found). The provided path is interpreted in a platform-specific - /// way at compile time. So, for instance, an invocation with a Windows path - /// containing backslashes `\` would not compile correctly on Unix. + ///
+ ///
     ///
-    /// Using this macro is often a bad idea, because if the file is
-    /// parsed as an expression, it is going to be placed in the
-    /// surrounding code unhygienically. This could result in variables
-    /// or functions being different from what the file expected if
-    /// there are variables or functions that have the same name in
-    /// the current file.
+    /// **Warning**: For multi-file Rust projects, the `include!` macro is probably not what you
+    /// are looking for. Usually, multi-file Rust projects use
+    /// [modules](https://doc.rust-lang.org/reference/items/modules.html). Multi-file projects and
+    /// modules are explained in the Rust-by-Example book
+    /// [here](https://doc.rust-lang.org/rust-by-example/mod/split.html) and the module system is
+    /// explained in the Rust Book
+    /// [here](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html).
     ///
+    /// 
+ ///
+ /// + /// If the included file is parsed as an expression, it is placed in the surrounding code + /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). This + /// could result in variables or functions being different from what the file expected if there + /// are variables or functions that have the same name in the current file. + /// + /// The included file is located relative to the current file (similarly to how modules are + /// found). The provided path is interpreted in a platform-specific way at compile time. So, + /// for instance, an invocation with a Windows path containing backslashes `\` would not + /// compile correctly on Unix. + /// + /// # Uses + /// + /// The `include!` macro is primarily used for two purposes. It is used to include + /// documentation that is written in a separate file and it is used to include [build artifacts + /// usually as a result from the `build.rs` + /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). + /// + /// When using the `include` macro to include stretches of documentation, remember that the + /// included file still needs to be a valid rust syntax. It is also possible to + /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or + /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain + /// text or markdown file. + /// /// # Examples - /// - /// Assume there are two files in the same directory with the following - /// contents: - /// + /// + /// Assume there are two files in the same directory with the following contents: + /// /// File 'monkeys.in': - /// + /// /// ```ignore (only-for-syntax-highlight) /// ['🙈', '🙊', '🙉'] /// .iter() @@ -1341,9 +1365,9 @@ pub(crate) mod builtin { /// .take(6) /// .collect::() /// ``` - /// + /// /// File 'main.rs': - /// + /// /// ```ignore (cannot-doctest-external-file-dependency) /// fn main() { /// let my_string = include!("monkeys.in"); @@ -1351,7 +1375,7 @@ pub(crate) mod builtin { /// println!("{my_string}"); /// } /// ``` - /// + /// /// Compiling 'main.rs' and running the resulting binary will print /// "🙈🙊🙉🙈🙊🙉". #[stable(feature = "rust1", since = "1.0.0")] From eb2980c7f1df7d4c461837daeca4c14eeea80429 Mon Sep 17 00:00:00 2001 From: Gijs Burghoorn Date: Wed, 4 Jan 2023 16:18:34 +0100 Subject: [PATCH 131/223] Tidy up whitespace --- library/core/src/macros/mod.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index b20e60ad96d1..ff80d1160f65 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1312,7 +1312,7 @@ pub(crate) mod builtin { /* compiler built-in */ }; } - + /// Parses a file as an expression or an item according to the context. /// ///
@@ -1328,19 +1328,19 @@ pub(crate) mod builtin { /// /// ///
- /// + /// /// If the included file is parsed as an expression, it is placed in the surrounding code /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). This /// could result in variables or functions being different from what the file expected if there /// are variables or functions that have the same name in the current file. - /// + /// /// The included file is located relative to the current file (similarly to how modules are /// found). The provided path is interpreted in a platform-specific way at compile time. So, /// for instance, an invocation with a Windows path containing backslashes `\` would not /// compile correctly on Unix. /// /// # Uses - /// + /// /// The `include!` macro is primarily used for two purposes. It is used to include /// documentation that is written in a separate file and it is used to include [build artifacts /// usually as a result from the `build.rs` @@ -1351,13 +1351,13 @@ pub(crate) mod builtin { /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain /// text or markdown file. - /// + /// /// # Examples - /// + /// /// Assume there are two files in the same directory with the following contents: - /// + /// /// File 'monkeys.in': - /// + /// /// ```ignore (only-for-syntax-highlight) /// ['🙈', '🙊', '🙉'] /// .iter() @@ -1365,9 +1365,9 @@ pub(crate) mod builtin { /// .take(6) /// .collect::() /// ``` - /// + /// /// File 'main.rs': - /// + /// /// ```ignore (cannot-doctest-external-file-dependency) /// fn main() { /// let my_string = include!("monkeys.in"); @@ -1375,7 +1375,7 @@ pub(crate) mod builtin { /// println!("{my_string}"); /// } /// ``` - /// + /// /// Compiling 'main.rs' and running the resulting binary will print /// "🙈🙊🙉🙈🙊🙉". #[stable(feature = "rust1", since = "1.0.0")] From f902200de4a722908919da701c05244fed3dabc5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Jan 2023 12:27:05 +0100 Subject: [PATCH 132/223] Add retry mechanism for rustdoc GUI tests to reduce flakyness --- src/tools/rustdoc-gui/tester.js | 122 ++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 46 deletions(-) diff --git a/src/tools/rustdoc-gui/tester.js b/src/tools/rustdoc-gui/tester.js index d40d9a3cb542..900ca3894362 100644 --- a/src/tools/rustdoc-gui/tester.js +++ b/src/tools/rustdoc-gui/tester.js @@ -9,6 +9,9 @@ const path = require("path"); const os = require('os'); const {Options, runTest} = require('browser-ui-test'); +// If a test fails or errors, we will retry it two more times in case it was a flaky failure. +const NB_RETRY = 3; + function showHelp() { console.log("rustdoc-js options:"); console.log(" --doc-folder [PATH] : location of the generated doc folder"); @@ -129,11 +132,59 @@ function char_printer(n_tests) { }; } -/// Sort array by .file_name property +// Sort array by .file_name property function by_filename(a, b) { return a.file_name - b.file_name; } +async function runTests(opts, framework_options, files, results, status_bar, showTestFailures) { + const tests_queue = []; + + for (const testPath of files) { + const callback = runTest(testPath, framework_options) + .then(out => { + const [output, nb_failures] = out; + results[nb_failures === 0 ? "successful" : "failed"].push({ + file_name: testPath, + output: output, + }); + if (nb_failures === 0) { + status_bar.successful(); + } else if (showTestFailures) { + status_bar.erroneous(); + } + }) + .catch(err => { + results.errored.push({ + file_name: testPath, + output: err, + }); + if (showTestFailures) { + status_bar.erroneous(); + } + }) + .finally(() => { + // We now remove the promise from the tests_queue. + tests_queue.splice(tests_queue.indexOf(callback), 1); + }); + tests_queue.push(callback); + if (opts["jobs"] > 0 && tests_queue.length >= opts["jobs"]) { + await Promise.race(tests_queue); + } + } + if (tests_queue.length > 0) { + await Promise.all(tests_queue); + } +} + +function createEmptyResults() { + return { + successful: [], + failed: [], + errored: [], + }; +} + async function main(argv) { let opts = parseOptions(argv.slice(2)); if (opts === null) { @@ -144,7 +195,7 @@ async function main(argv) { let debug = false; // Run tests in sequentially let headless = true; - const options = new Options(); + const framework_options = new Options(); try { // This is more convenient that setting fields one by one. let args = [ @@ -169,13 +220,12 @@ async function main(argv) { args.push("--executable-path"); args.push(opts["executable_path"]); } - options.parseArguments(args); + framework_options.parseArguments(args); } catch (error) { console.error(`invalid argument: ${error}`); process.exit(1); } - let failed = false; let files; if (opts["files"].length === 0) { files = fs.readdirSync(opts["tests_folder"]); @@ -187,6 +237,9 @@ async function main(argv) { console.error("rustdoc-gui: No test selected"); process.exit(2); } + files.forEach((file_name, index) => { + files[index] = path.join(opts["tests_folder"], file_name); + }); files.sort(); if (!headless) { @@ -215,52 +268,29 @@ async function main(argv) { }; process.on('exit', exitHandling); - const tests_queue = []; - let results = { - successful: [], - failed: [], - errored: [], - }; + const originalFilesLen = files.length; + let results = createEmptyResults(); const status_bar = char_printer(files.length); - for (let i = 0; i < files.length; ++i) { - const file_name = files[i]; - const testPath = path.join(opts["tests_folder"], file_name); - const callback = runTest(testPath, options) - .then(out => { - const [output, nb_failures] = out; - results[nb_failures === 0 ? "successful" : "failed"].push({ - file_name: testPath, - output: output, - }); - if (nb_failures > 0) { - status_bar.erroneous(); - failed = true; - } else { - status_bar.successful(); - } - }) - .catch(err => { - results.errored.push({ - file_name: testPath + file_name, - output: err, - }); - status_bar.erroneous(); - failed = true; - }) - .finally(() => { - // We now remove the promise from the tests_queue. - tests_queue.splice(tests_queue.indexOf(callback), 1); - }); - tests_queue.push(callback); - if (opts["jobs"] > 0 && tests_queue.length >= opts["jobs"]) { - await Promise.race(tests_queue); + + let new_results; + for (let it = 0; it < NB_RETRY && files.length > 0; ++it) { + new_results = createEmptyResults(); + await runTests(opts, framework_options, files, new_results, status_bar, it + 1 >= NB_RETRY); + Array.prototype.push.apply(results.successful, new_results.successful); + // We generate the new list of files with the previously failing tests. + files = Array.prototype.concat(new_results.failed, new_results.errored); + if (files.length > originalFilesLen / 2) { + // If we have too many failing tests, it's very likely not flaky failures anymore so + // no need to retry. + break; } } - if (tests_queue.length > 0) { - await Promise.all(tests_queue); - } + status_bar.finish(); + Array.prototype.push.apply(results.failed, new_results.failed); + Array.prototype.push.apply(results.errored, new_results.errored); + // We don't need this listener anymore. process.removeListener("exit", exitHandling); @@ -287,7 +317,7 @@ async function main(argv) { }); } - if (failed) { + if (results.failed.length > 0 || results.errored.length > 0) { process.exit(1); } } From 6306fd3be407fa526785d2222f4cb00ed1f01abf Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 4 Jan 2023 15:33:59 +0000 Subject: [PATCH 133/223] Update cargo 8 commits in 2381cbdb4e9b07090f552d34a44a529b6e620e44..8c460b2237a6359a7e3335890db8da049bdd62fc 2022-12-23 12:19:27 +0000 to 2023-01-04 14:30:01 +0000 - test: revive nightly plugin tests to work (rust-lang/cargo#11534) - Add note to release notes about rejecting multiple registries. (rust-lang/cargo#11531) - Fix a typo `fresheness` -> `freshness` (rust-lang/cargo#11529) - Reasons for rebuilding (rust-lang/cargo#11407) - Asymmetric tokens (rust-lang/cargo#10771) - Use proper git URL for GitHub repos (rust-lang/cargo#11517) - Add `registry.default` example (rust-lang/cargo#11516) - Support vendoring with different revs from same git repo (rust-lang/cargo#10690) Also update license exceptions and permitted dependencies for new cargo dependency "pasetors". A new dependency `getrandom` is added into `rustc-workspace-hacks`, since it requires feature `js`. --- Cargo.lock | 394 +++++++++++++++++++++- src/tools/cargo | 2 +- src/tools/rustc-workspace-hack/Cargo.toml | 2 + src/tools/tidy/src/deps.rs | 12 + 4 files changed, 392 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46b0a01a18ec..d7381b6c9386 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,6 +197,18 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base64ct" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf" + [[package]] name = "bitflags" version = "1.3.2" @@ -271,6 +283,12 @@ dependencies = [ "toml", ] +[[package]] +name = "bumpalo" +version = "3.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" + [[package]] name = "bytecount" version = "0.6.2" @@ -341,6 +359,7 @@ dependencies = [ "opener", "openssl", "os_info", + "pasetors", "pathdiff", "percent-encoding", "pretty_env_logger", @@ -358,6 +377,7 @@ dependencies = [ "tar", "tempfile", "termcolor", + "time 0.3.17", "toml_edit", "unicode-width", "unicode-xid", @@ -443,10 +463,13 @@ dependencies = [ "glob", "itertools", "lazy_static", + "pasetors", + "serde", "serde_json", "snapbox", "tar", "termcolor", + "time 0.3.17", "toml_edit", "url", "winapi", @@ -585,7 +608,7 @@ dependencies = [ "num-integer", "num-traits", "serde", - "time", + "time 0.1.43", "winapi", ] @@ -899,6 +922,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82a90734b3d5dcf656e7624cca6bce9c3a90ee11f900e80141a7427ccfb3d317" +[[package]] +name = "const-oid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b" + [[package]] name = "content_inspector" version = "0.2.4" @@ -953,7 +982,7 @@ dependencies = [ [[package]] name = "crates-io" -version = "0.35.0" +version = "0.35.1" dependencies = [ "anyhow", "curl", @@ -1016,12 +1045,25 @@ dependencies = [ ] [[package]] -name = "crypto-common" -version = "0.1.2" +name = "crypto-bigint" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4600d695eb3f6ce1cd44e6e291adceb2cc3ab12f20a33777ecd0bf6eba34e06" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" dependencies = [ "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", ] [[package]] @@ -1046,6 +1088,12 @@ dependencies = [ "quote", ] +[[package]] +name = "ct-codecs" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3b7eb4404b8195a9abb6356f4ac07d8ba267045c8d6d220ac4dc992e6cc75df" + [[package]] name = "ctor" version = "0.1.26" @@ -1102,6 +1150,17 @@ dependencies = [ "syn", ] +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "derive-new" version = "0.5.8" @@ -1140,12 +1199,13 @@ checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "digest" -version = "0.10.2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb780dce4f9a8f5c087362b3a4595936b2019e7c8b30f2c3e9a7e94e6ae9837" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -1232,6 +1292,27 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der", + "elliptic-curve", + "rfc6979", + "signature", +] + +[[package]] +name = "ed25519-compact" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a3d382e8464107391c8706b4c14b087808ecb909f6c15c34114bc42e53a9e4c" +dependencies = [ + "getrandom 0.2.8", +] + [[package]] name = "either" version = "1.6.0" @@ -1250,6 +1331,28 @@ dependencies = [ "serde_json", ] +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct", + "crypto-bigint", + "der", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "ena" version = "0.14.0" @@ -1369,6 +1472,22 @@ dependencies = [ "instant", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90" + [[package]] name = "filetime" version = "0.2.14" @@ -1644,8 +1763,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1708,6 +1829,17 @@ dependencies = [ "regex", ] +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "gsgdt" version = "0.1.2" @@ -1797,6 +1929,24 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +[[package]] +name = "hkdf" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "home" version = "0.5.3" @@ -1961,7 +2111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af1955a75fa080c677d3972822ec4bad316169ab1cfc6c257a942c2265dbe5fe" dependencies = [ "bitmaps", - "rand_core 0.6.2", + "rand_core 0.6.4", "rand_xoshiro", "sized-chunks", "typenum", @@ -2094,6 +2244,15 @@ dependencies = [ "libc", ] +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "jsondocck" version = "0.1.0" @@ -2664,6 +2823,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "orion" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2baf7fd2e326e3895c681176788dd227fcd8369350e53c570592d8563fecbb6" +dependencies = [ + "fiat-crypto", + "subtle", + "zeroize", +] + [[package]] name = "os_info" version = "3.5.0" @@ -2696,6 +2866,17 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa", + "elliptic-curve", + "sha2", +] + [[package]] name = "packed_simd_2" version = "0.3.8" @@ -2777,12 +2958,42 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "pasetors" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed20c4c21d893414f42e0cbfebe8a8036b5ae9b0264611fb6504e395eda6ceec" +dependencies = [ + "ct-codecs", + "ed25519-compact", + "getrandom 0.2.8", + "orion", + "p384", + "rand_core 0.6.4", + "regex", + "serde", + "serde_json", + "sha2", + "subtle", + "time 0.3.17", + "zeroize", +] + [[package]] name = "pathdiff" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -2902,6 +3113,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -3094,7 +3315,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha 0.3.0", - "rand_core 0.6.2", + "rand_core 0.6.4", ] [[package]] @@ -3114,7 +3335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" dependencies = [ "ppv-lite86", - "rand_core 0.6.2", + "rand_core 0.6.4", ] [[package]] @@ -3128,9 +3349,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.8", ] @@ -3159,7 +3380,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" dependencies = [ - "rand_core 0.6.2", + "rand_core 0.6.4", ] [[package]] @@ -3265,6 +3486,17 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint", + "hmac", + "zeroize", +] + [[package]] name = "rls" version = "2.0.0" @@ -3404,6 +3636,7 @@ version = "1.0.0" dependencies = [ "bstr 0.2.17", "clap 3.2.20", + "getrandom 0.2.8", "libc", "libz-sys", "rand 0.8.5", @@ -4793,6 +5026,20 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.0.0" @@ -4895,9 +5142,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ "cfg-if", "cpufeatures", @@ -4925,6 +5172,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "similar" version = "2.1.0" @@ -5028,6 +5285,16 @@ dependencies = [ "uuid", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -5150,6 +5417,12 @@ dependencies = [ "syn", ] +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" version = "1.0.107" @@ -5347,6 +5620,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "time" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +dependencies = [ + "itoa", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +dependencies = [ + "time-core", +] + [[package]] name = "tinystr" version = "0.7.0" @@ -5530,9 +5830,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.12.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-parse" @@ -5856,6 +6156,60 @@ dependencies = [ "rustc-std-workspace-core", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + [[package]] name = "winapi" version = "0.3.9" @@ -6048,6 +6402,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" + [[package]] name = "zerovec" version = "0.9.0" diff --git a/src/tools/cargo b/src/tools/cargo index 2381cbdb4e9b..8c460b2237a6 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 2381cbdb4e9b07090f552d34a44a529b6e620e44 +Subproject commit 8c460b2237a6359a7e3335890db8da049bdd62fc diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml index a5f0c0f320a8..84b16a37a338 100644 --- a/src/tools/rustc-workspace-hack/Cargo.toml +++ b/src/tools/rustc-workspace-hack/Cargo.toml @@ -77,6 +77,8 @@ clap = { version = "3.1.1", features = ["derive", "clap_derive"]} curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true } # Ensure `extra_traits` of libc, which is used transitively by Cargo. libc = { version = "0.2", features = ["extra_traits"] } +# Ensure `js` of getrandom, which is (unfortunately) used transitively by Cargo. +getrandom = { version = "0.2", features = ["js"] } # Ensure default features of libz-sys, which are disabled in some scenarios. libz-sys = { version = "1.1.2" } # Ensure default features of regex, which are disabled in some scenarios. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 75454cbdc5fe..f649e391b798 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -40,6 +40,8 @@ const EXCEPTIONS: &[(&str, &str)] = &[ ("im-rc", "MPL-2.0+"), // cargo ("sized-chunks", "MPL-2.0+"), // cargo via im-rc ("bitmaps", "MPL-2.0+"), // cargo via im-rc + ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), // cargo via pasetors + ("subtle", "BSD-3-Clause"), // cargo via pasetors ("instant", "BSD-3-Clause"), // rustc_driver/tracing-subscriber/parking_lot ("snap", "BSD-3-Clause"), // rustc ("fluent-langneg", "Apache-2.0"), // rustc (fluent translations) @@ -96,6 +98,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "autocfg", "bitflags", "block-buffer", + "bumpalo", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "cc", "cfg-if", "chalk-derive", @@ -153,6 +156,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "itertools", "itoa", "jobserver", + "js-sys", // Included in Cargo's dep graph but only activated on wasm32-*-unknown. "lazy_static", "libc", "libloading", @@ -222,6 +226,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "stable_deref_trait", "stacker", "static_assertions", + "subtle", // dependency of cargo (via pasetors) "syn", "synstructure", "tempfile", @@ -264,6 +269,13 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "valuable", "version_check", "wasi", + // vvv Included in Cargo's dep graph but only activated on wasm32-*-unknown. + "wasm-bindgen", + "wasm-bindgen-backend", + "wasm-bindgen-macro", + "wasm-bindgen-macro-support", + "wasm-bindgen-shared", + // ^^^ Included in Cargo's dep graph but only activated on wasm32-*-unknown. "winapi", "winapi-i686-pc-windows-gnu", "winapi-util", From 8f80a23c252d08d83083b79036ee7199d3164eb9 Mon Sep 17 00:00:00 2001 From: KaDiWa Date: Wed, 4 Jan 2023 18:15:43 +0100 Subject: [PATCH 134/223] adjust comments about pre-push.sh hook --- src/bootstrap/setup.rs | 4 ++-- src/etc/pre-push.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index cd360cbef965..ca4feac6fac7 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -351,7 +351,7 @@ pub fn interactive_path() -> io::Result { Ok(template) } -// install a git hook to automatically run tidy --bless, if they want +// install a git hook to automatically run tidy, if they want fn install_git_hook_maybe(config: &Config) -> io::Result<()> { let git = t!(config.git().args(&["rev-parse", "--git-common-dir"]).output().map(|output| { assert!(output.status.success(), "failed to run `git`"); @@ -367,7 +367,7 @@ fn install_git_hook_maybe(config: &Config) -> io::Result<()> { println!(); println!( "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality. -If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` before +If you'd like, x.py can install a git hook for you that will automatically run `test tidy` before pushing your code to ensure your code is up to par. If you decide later that this behavior is undesirable, simply delete the `pre-push` file from .git/hooks." ); diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh index 2a3086338b4b..7a846d44ad6a 100755 --- a/src/etc/pre-push.sh +++ b/src/etc/pre-push.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Call `tidy --bless` before git push +# Call `tidy` before git push # Copy this script to .git/hooks to activate, # and remove it from .git/hooks to deactivate. # From a4974fa9c7b5a0a74af5912f560c83f6d2ac78f6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 2 Jan 2023 23:12:47 +0000 Subject: [PATCH 135/223] Split `-Zchalk` flag into `-Ztrait-solver=(stock|chalk|next)` flag --- compiler/rustc_interface/src/tests.rs | 3 ++- compiler/rustc_session/src/config.rs | 13 ++++++++++++- compiler/rustc_session/src/options.rs | 16 ++++++++++++++-- .../rustc_trait_selection/src/traits/engine.rs | 18 ++++++++++-------- .../src/traits/error_reporting/mod.rs | 3 ++- .../src/traits/select/confirmation.rs | 4 ++-- compiler/rustc_ty_utils/src/ty.rs | 3 ++- 7 files changed, 44 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9ec71c6b87ed..316e2e29cd8b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -4,6 +4,7 @@ use crate::interface::parse_cfgspecs; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; use rustc_session::config::rustc_optgroups; +use rustc_session::config::TraitSolver; use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; use rustc_session::config::{ BranchProtection, Externs, OomStrategy, OutputType, OutputTypes, PAuthKey, PacRet, @@ -722,7 +723,6 @@ fn test_unstable_options_tracking_hash() { pac_ret: Some(PacRet { leaf: true, key: PAuthKey::B }) }) ); - tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(debug_info_for_profiling, true); @@ -792,6 +792,7 @@ fn test_unstable_options_tracking_hash() { tracked!(thinlto, Some(true)); tracked!(thir_unsafeck, true); tracked!(tls_model, Some(TlsModel::GeneralDynamic)); + tracked!(trait_solver, TraitSolver::Chalk); tracked!(translate_remapped_path_to_local_path, false); tracked!(trap_unreachable, Some(false)); tracked!(treat_err_as_bug, NonZeroUsize::new(1)); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5f78f6d079d0..4f1175856dc3 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -554,6 +554,16 @@ pub enum PrintRequest { SplitDebuginfo, } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum TraitSolver { + /// Stock trait solver in `rustc_trait_selection::traits::select` + Stock, + /// Chalk trait solver + Chalk, + /// Experimental trait solver in `rustc_trait_selection::solve` + Next, +} + pub enum Input { /// Load source code from a file. File(PathBuf), @@ -2761,7 +2771,7 @@ pub(crate) mod dep_tracking { BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType, InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel, OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind, - SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, + SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths, }; use crate::lint; use crate::options::WasiExecModel; @@ -2861,6 +2871,7 @@ pub(crate) mod dep_tracking { BranchProtection, OomStrategy, LanguageIdentifier, + TraitSolver, ); impl DepTrackingHash for (T1, T2) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b379aef80fb2..9ce50246b08a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -382,6 +382,8 @@ mod desc { "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; + pub const parse_trait_solver: &str = + "one of the supported solver modes (`stock`, `chalk`, or `next`)"; pub const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = @@ -880,6 +882,16 @@ mod parse { } } + pub(crate) fn parse_trait_solver(slot: &mut TraitSolver, v: Option<&str>) -> bool { + match v { + Some("stock") => *slot = TraitSolver::Stock, + Some("chalk") => *slot = TraitSolver::Chalk, + Some("next") => *slot = TraitSolver::Next, + _ => return false, + } + true + } + pub(crate) fn parse_lto(slot: &mut LtoCli, v: Option<&str>) -> bool { if v.is_some() { let mut bool_arg = None; @@ -1249,8 +1261,6 @@ options! { "instrument control-flow architecture protection"), cgu_partitioning_strategy: Option = (None, parse_opt_string, [TRACKED], "the codegen unit partitioning strategy to use"), - chalk: bool = (false, parse_bool, [TRACKED], - "enable the experimental Chalk-based trait solving engine"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), combine_cgu: bool = (false, parse_bool, [TRACKED], @@ -1609,6 +1619,8 @@ options! { "for every macro invocation, print its name and arguments (default: no)"), track_diagnostics: bool = (false, parse_bool, [UNTRACKED], "tracks where in rustc a diagnostic was emitted"), + trait_solver: TraitSolver = (TraitSolver::Stock, parse_trait_solver, [TRACKED], + "specify the trait solver mode used by rustc (default: stock)"), // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index c028e89e4ea2..bd56d058a490 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use super::TraitEngine; use super::{ChalkFulfillmentContext, FulfillmentContext}; +use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::traits::NormalizeExt; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -20,6 +21,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::ToPredicate; use rustc_middle::ty::TypeFoldable; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_session::config::TraitSolver; use rustc_span::Span; pub trait TraitEngineExt<'tcx> { @@ -29,18 +31,18 @@ pub trait TraitEngineExt<'tcx> { impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Box { - if tcx.sess.opts.unstable_opts.chalk { - Box::new(ChalkFulfillmentContext::new()) - } else { - Box::new(FulfillmentContext::new()) + match tcx.sess.opts.unstable_opts.trait_solver { + TraitSolver::Stock => Box::new(FulfillmentContext::new()), + TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new()), + TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()), } } fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box { - if tcx.sess.opts.unstable_opts.chalk { - Box::new(ChalkFulfillmentContext::new_in_snapshot()) - } else { - Box::new(FulfillmentContext::new_in_snapshot()) + match tcx.sess.opts.unstable_opts.trait_solver { + TraitSolver::Stock => Box::new(FulfillmentContext::new_in_snapshot()), + TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new_in_snapshot()), + TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()), } } } 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 8a08c7533aa1..ac52316d9c91 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -40,6 +40,7 @@ use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, TypeVisitable, }; +use rustc_session::config::TraitSolver; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::symbol::sym; @@ -1167,7 +1168,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::WellFormed(ty) => { - if !self.tcx.sess.opts.unstable_opts.chalk { + if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk { // WF predicates cannot themselves make // errors. They can only block due to // ambiguity; otherwise, they always diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 466641ea6df3..15526b34ed2d 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -15,6 +15,7 @@ use rustc_middle::ty::{ self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, }; +use rustc_session::config::TraitSolver; use rustc_span::def_id::DefId; use crate::traits::project::{normalize_with_depth, normalize_with_depth_to}; @@ -767,8 +768,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations"); // FIXME: Chalk - - if !self.tcx().sess.opts.unstable_opts.chalk { + if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk { nested.push(obligation.with( self.tcx(), ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)), diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index e2d10f550c32..86afac113d79 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt}; +use rustc_session::config::TraitSolver; use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( @@ -121,7 +122,7 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // are any errors at that point, so outside of type inference you can be // sure that this will succeed without errors anyway. - if tcx.sess.opts.unstable_opts.chalk { + if tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Chalk { let environment = well_formed_types_in_env(tcx, def_id); predicates.extend(environment); } From 1e81f9a47fb801fab1c06ba40b06347ffebbd066 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 2 Jan 2023 23:18:00 +0000 Subject: [PATCH 136/223] Update tests, etc --- src/test/rustdoc-ui/z-help.stdout | 2 +- src/test/ui/chalkify/arithmetic.rs | 2 +- src/test/ui/chalkify/assert.rs | 2 +- src/test/ui/chalkify/basic.rs | 2 +- src/test/ui/chalkify/bugs/async.rs | 2 +- src/test/ui/chalkify/builtin-copy-clone.rs | 2 +- src/test/ui/chalkify/chalk_initial_program.rs | 2 +- src/test/ui/chalkify/closure.rs | 2 +- src/test/ui/chalkify/generic_impls.rs | 2 +- src/test/ui/chalkify/impl_wf.rs | 2 +- src/test/ui/chalkify/impl_wf_2.rs | 2 +- src/test/ui/chalkify/inherent_impl.rs | 2 +- src/test/ui/chalkify/inherent_impl_min.rs | 2 +- src/test/ui/chalkify/lower_env1.rs | 2 +- src/test/ui/chalkify/lower_env2.rs | 2 +- src/test/ui/chalkify/lower_env3.rs | 2 +- src/test/ui/chalkify/lower_impl.rs | 2 +- src/test/ui/chalkify/lower_struct.rs | 2 +- src/test/ui/chalkify/lower_trait.rs | 2 +- src/test/ui/chalkify/lower_trait_higher_rank.rs | 2 +- src/test/ui/chalkify/lower_trait_where_clause.rs | 2 +- src/test/ui/chalkify/println.rs | 2 +- src/test/ui/chalkify/projection.rs | 2 +- src/test/ui/chalkify/recursive_where_clause_on_type.rs | 2 +- src/test/ui/chalkify/super_trait.rs | 2 +- src/test/ui/chalkify/trait-objects.rs | 2 +- src/test/ui/chalkify/trait_implied_bound.rs | 2 +- src/test/ui/chalkify/type_implied_bound.rs | 2 +- src/test/ui/chalkify/type_inference.rs | 2 +- src/test/ui/chalkify/type_wf.rs | 2 +- src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs | 2 +- src/tools/compiletest/src/runtest.rs | 2 +- 32 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 9bd6c5fedf54..0464613dc6e7 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -8,7 +8,6 @@ -Z branch-protection=val -- set options for branch target identification and pointer authentication on AArch64 -Z cf-protection=val -- instrument control-flow architecture protection -Z cgu-partitioning-strategy=val -- the codegen unit partitioning strategy to use - -Z chalk=val -- enable the experimental Chalk-based trait solving engine -Z codegen-backend=val -- the backend to use -Z combine-cgu=val -- combine CGUs into a single one -Z crate-attr=val -- inject the given attribute in the crate @@ -175,6 +174,7 @@ -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) -Z trace-macros=val -- for every macro invocation, print its name and arguments (default: no) -Z track-diagnostics=val -- tracks where in rustc a diagnostic was emitted + -Z trait-solver=val -- specify the trait solver mode used by rustc (default: stock) -Z translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) -Z translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics -Z translate-lang=val -- language identifier for diagnostic output diff --git a/src/test/ui/chalkify/arithmetic.rs b/src/test/ui/chalkify/arithmetic.rs index a20acce4c76b..6c78a71b0fc9 100644 --- a/src/test/ui/chalkify/arithmetic.rs +++ b/src/test/ui/chalkify/arithmetic.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk fn main() { 1 + 2; diff --git a/src/test/ui/chalkify/assert.rs b/src/test/ui/chalkify/assert.rs index f4ebf91924ce..834c8935e762 100644 --- a/src/test/ui/chalkify/assert.rs +++ b/src/test/ui/chalkify/assert.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk fn main() { assert_eq!(1, 1); diff --git a/src/test/ui/chalkify/basic.rs b/src/test/ui/chalkify/basic.rs index dbd60fc8bb1f..4a7cd9396690 100644 --- a/src/test/ui/chalkify/basic.rs +++ b/src/test/ui/chalkify/basic.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo {} diff --git a/src/test/ui/chalkify/bugs/async.rs b/src/test/ui/chalkify/bugs/async.rs index ae5224dbd6fa..ed0f5dc9bd37 100644 --- a/src/test/ui/chalkify/bugs/async.rs +++ b/src/test/ui/chalkify/bugs/async.rs @@ -1,6 +1,6 @@ // check-fail // known-bug: unknown -// compile-flags: -Z chalk --edition=2021 +// compile-flags: -Z trait-solver=chalk --edition=2021 fn main() -> () {} diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs index 7712e9465424..a478c006ef1c 100644 --- a/src/test/ui/chalkify/builtin-copy-clone.rs +++ b/src/test/ui/chalkify/builtin-copy-clone.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk // Test that `Clone` is correctly implemented for builtin types. diff --git a/src/test/ui/chalkify/chalk_initial_program.rs b/src/test/ui/chalkify/chalk_initial_program.rs index df25bad622b3..21de72b6fccc 100644 --- a/src/test/ui/chalkify/chalk_initial_program.rs +++ b/src/test/ui/chalkify/chalk_initial_program.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/closure.rs b/src/test/ui/chalkify/closure.rs index 568e2e30c418..a908a1e97ecd 100644 --- a/src/test/ui/chalkify/closure.rs +++ b/src/test/ui/chalkify/closure.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk fn main() -> () { let t = || {}; diff --git a/src/test/ui/chalkify/generic_impls.rs b/src/test/ui/chalkify/generic_impls.rs index d70c6f8055dd..7d33e12d8be1 100644 --- a/src/test/ui/chalkify/generic_impls.rs +++ b/src/test/ui/chalkify/generic_impls.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/impl_wf.rs b/src/test/ui/chalkify/impl_wf.rs index 66f57c2d1100..c8dfd4c3a5b4 100644 --- a/src/test/ui/chalkify/impl_wf.rs +++ b/src/test/ui/chalkify/impl_wf.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo: Sized { } diff --git a/src/test/ui/chalkify/impl_wf_2.rs b/src/test/ui/chalkify/impl_wf_2.rs index 758a7185e391..325044ad6349 100644 --- a/src/test/ui/chalkify/impl_wf_2.rs +++ b/src/test/ui/chalkify/impl_wf_2.rs @@ -1,6 +1,6 @@ // Split out of impl_wf.rs to work around rust aborting compilation early -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo: Sized { } diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs index a2730219fbe2..f0f24d485cd8 100644 --- a/src/test/ui/chalkify/inherent_impl.rs +++ b/src/test/ui/chalkify/inherent_impl.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/inherent_impl_min.rs b/src/test/ui/chalkify/inherent_impl_min.rs index 774c46e401ca..3eda7102decd 100644 --- a/src/test/ui/chalkify/inherent_impl_min.rs +++ b/src/test/ui/chalkify/inherent_impl_min.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs index e3c756959214..c8762001e6a1 100644 --- a/src/test/ui/chalkify/lower_env1.rs +++ b/src/test/ui/chalkify/lower_env1.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk #![allow(dead_code)] diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs index b5432ce0e307..7d4f81f12eaf 100644 --- a/src/test/ui/chalkify/lower_env2.rs +++ b/src/test/ui/chalkify/lower_env2.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk #![allow(dead_code)] diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs index 673f08d78abd..5b70c4abbb55 100644 --- a/src/test/ui/chalkify/lower_env3.rs +++ b/src/test/ui/chalkify/lower_env3.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk #![allow(dead_code)] diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs index f586cf083915..6f79b3ba386a 100644 --- a/src/test/ui/chalkify/lower_impl.rs +++ b/src/test/ui/chalkify/lower_impl.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs index 94a0716d3835..6be0d4dd5bd2 100644 --- a/src/test/ui/chalkify/lower_struct.rs +++ b/src/test/ui/chalkify/lower_struct.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk struct Foo<'a, T> where Box: Clone { _x: std::marker::PhantomData<&'a T>, diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs index d8f6180ceb31..8f5b358220bf 100644 --- a/src/test/ui/chalkify/lower_trait.rs +++ b/src/test/ui/chalkify/lower_trait.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Bar { } diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs index a48979491a10..f04a1deea875 100644 --- a/src/test/ui/chalkify/lower_trait_higher_rank.rs +++ b/src/test/ui/chalkify/lower_trait_higher_rank.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 { diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs index 19cff8db7cb4..a21d2f31963c 100644 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ b/src/test/ui/chalkify/lower_trait_where_clause.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk use std::borrow::Borrow; diff --git a/src/test/ui/chalkify/println.rs b/src/test/ui/chalkify/println.rs index 0f0df29019e7..edddc3821523 100644 --- a/src/test/ui/chalkify/println.rs +++ b/src/test/ui/chalkify/println.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk fn main() { println!("hello"); diff --git a/src/test/ui/chalkify/projection.rs b/src/test/ui/chalkify/projection.rs index d6a8dd7a4a20..19bb2ae14972 100644 --- a/src/test/ui/chalkify/projection.rs +++ b/src/test/ui/chalkify/projection.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.rs b/src/test/ui/chalkify/recursive_where_clause_on_type.rs index 87324a5f79bd..5855f000c7b9 100644 --- a/src/test/ui/chalkify/recursive_where_clause_on_type.rs +++ b/src/test/ui/chalkify/recursive_where_clause_on_type.rs @@ -1,6 +1,6 @@ // FIXME(chalk): should fail, see comments // check-fail -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk #![feature(trivial_bounds)] diff --git a/src/test/ui/chalkify/super_trait.rs b/src/test/ui/chalkify/super_trait.rs index eeff9fd9b80a..540ae51e57f6 100644 --- a/src/test/ui/chalkify/super_trait.rs +++ b/src/test/ui/chalkify/super_trait.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } trait Bar: Foo { } diff --git a/src/test/ui/chalkify/trait-objects.rs b/src/test/ui/chalkify/trait-objects.rs index d56abc42bf54..144d9788b82e 100644 --- a/src/test/ui/chalkify/trait-objects.rs +++ b/src/test/ui/chalkify/trait-objects.rs @@ -1,5 +1,5 @@ // check-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk use std::fmt::Display; diff --git a/src/test/ui/chalkify/trait_implied_bound.rs b/src/test/ui/chalkify/trait_implied_bound.rs index 8a2e1cf59900..f97dbf6b7e77 100644 --- a/src/test/ui/chalkify/trait_implied_bound.rs +++ b/src/test/ui/chalkify/trait_implied_bound.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } trait Bar where U: Foo { } diff --git a/src/test/ui/chalkify/type_implied_bound.rs b/src/test/ui/chalkify/type_implied_bound.rs index 8673f5319bdf..70f1b4265e49 100644 --- a/src/test/ui/chalkify/type_implied_bound.rs +++ b/src/test/ui/chalkify/type_implied_bound.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Eq { } trait Hash: Eq { } diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs index 369777a7904a..d7167d0dc57f 100644 --- a/src/test/ui/chalkify/type_inference.rs +++ b/src/test/ui/chalkify/type_inference.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } impl Foo for i32 { } diff --git a/src/test/ui/chalkify/type_wf.rs b/src/test/ui/chalkify/type_wf.rs index eeeefcfb7dd1..37d2f5ca832c 100644 --- a/src/test/ui/chalkify/type_wf.rs +++ b/src/test/ui/chalkify/type_wf.rs @@ -1,5 +1,5 @@ // check-fail -// compile-flags: -Z chalk +// compile-flags: -Z trait-solver=chalk trait Foo { } diff --git a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs index 79844dcbdacf..c177655c5acf 100644 --- a/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs +++ b/src/test/ui/implied-bounds/hrlt-implied-trait-bounds-guard.rs @@ -1,5 +1,5 @@ // A test exploiting the bug behind #25860 except with -// implied trait bounds which currently don't exist without `-Zchalk`. +// implied trait bounds which currently don't exist without `-Ztrait-solver=chalk`. use std::marker::PhantomData; struct Foo<'a, 'b, T>(PhantomData<(&'a (), &'b (), T)>) where diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 7a3c0d28fc3e..7e48dd206606 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2011,7 +2011,7 @@ impl<'test> TestCx<'test> { rustc.args(&["-Zpolonius"]); } Some(CompareMode::Chalk) => { - rustc.args(&["-Zchalk"]); + rustc.args(&["-Ztrait-solver=chalk"]); } Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => { rustc.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]); From 8b0f43b19dcd97cc6b31c2d02b5526a48dd93c06 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Jan 2023 16:49:38 +0000 Subject: [PATCH 137/223] Rename stock solver to classic --- compiler/rustc_session/src/config.rs | 4 ++-- compiler/rustc_session/src/options.rs | 10 ++++++---- compiler/rustc_trait_selection/src/traits/engine.rs | 4 ++-- src/test/rustdoc-ui/z-help.stdout | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 4f1175856dc3..a87e820386e7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -556,8 +556,8 @@ pub enum PrintRequest { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum TraitSolver { - /// Stock trait solver in `rustc_trait_selection::traits::select` - Stock, + /// Classic trait solver in `rustc_trait_selection::traits::select` + Classic, /// Chalk trait solver Chalk, /// Experimental trait solver in `rustc_trait_selection::solve` diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 9ce50246b08a..043a60a1c531 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -383,7 +383,7 @@ mod desc { pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a number bigger than 0"; pub const parse_trait_solver: &str = - "one of the supported solver modes (`stock`, `chalk`, or `next`)"; + "one of the supported solver modes (`classic`, `chalk`, or `next`)"; pub const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub const parse_linker_plugin_lto: &str = @@ -884,9 +884,11 @@ mod parse { pub(crate) fn parse_trait_solver(slot: &mut TraitSolver, v: Option<&str>) -> bool { match v { - Some("stock") => *slot = TraitSolver::Stock, + Some("classic") => *slot = TraitSolver::Classic, Some("chalk") => *slot = TraitSolver::Chalk, Some("next") => *slot = TraitSolver::Next, + // default trait solver is subject to change.. + Some("default") => *slot = TraitSolver::Classic, _ => return false, } true @@ -1619,8 +1621,8 @@ options! { "for every macro invocation, print its name and arguments (default: no)"), track_diagnostics: bool = (false, parse_bool, [UNTRACKED], "tracks where in rustc a diagnostic was emitted"), - trait_solver: TraitSolver = (TraitSolver::Stock, parse_trait_solver, [TRACKED], - "specify the trait solver mode used by rustc (default: stock)"), + trait_solver: TraitSolver = (TraitSolver::Classic, parse_trait_solver, [TRACKED], + "specify the trait solver mode used by rustc (default: classic)"), // Diagnostics are considered side-effects of a query (see `QuerySideEffects`) and are saved // alongside query results and changes to translation options can affect diagnostics - so // translation options should be tracked. diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index bd56d058a490..bc6d9d4b922d 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -32,7 +32,7 @@ pub trait TraitEngineExt<'tcx> { impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Box { match tcx.sess.opts.unstable_opts.trait_solver { - TraitSolver::Stock => Box::new(FulfillmentContext::new()), + TraitSolver::Classic => Box::new(FulfillmentContext::new()), TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new()), TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()), } @@ -40,7 +40,7 @@ impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { fn new_in_snapshot(tcx: TyCtxt<'tcx>) -> Box { match tcx.sess.opts.unstable_opts.trait_solver { - TraitSolver::Stock => Box::new(FulfillmentContext::new_in_snapshot()), + TraitSolver::Classic => Box::new(FulfillmentContext::new_in_snapshot()), TraitSolver::Chalk => Box::new(ChalkFulfillmentContext::new_in_snapshot()), TraitSolver::Next => Box::new(NextFulfillmentCtxt::new()), } diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index 0464613dc6e7..537dc92be192 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -174,7 +174,7 @@ -Z tls-model=val -- choose the TLS model to use (`rustc --print tls-models` for details) -Z trace-macros=val -- for every macro invocation, print its name and arguments (default: no) -Z track-diagnostics=val -- tracks where in rustc a diagnostic was emitted - -Z trait-solver=val -- specify the trait solver mode used by rustc (default: stock) + -Z trait-solver=val -- specify the trait solver mode used by rustc (default: classic) -Z translate-additional-ftl=val -- additional fluent translation to preferentially use (for testing translation) -Z translate-directionality-markers=val -- emit directionality isolation markers in translated diagnostics -Z translate-lang=val -- language identifier for diagnostic output From 7ffcedf6659d30c4a076d89b2586b385ad2f2d16 Mon Sep 17 00:00:00 2001 From: Caio Date: Wed, 4 Jan 2023 16:44:30 -0300 Subject: [PATCH 138/223] Move tests --- src/test/ui/{issues => associated-consts}/issue-105330.rs | 0 src/test/ui/{issues => associated-consts}/issue-105330.stderr | 0 src/test/ui/{issues => associated-types}/issue-25700-1.rs | 0 src/test/ui/{issues => associated-types}/issue-25700-2.rs | 0 src/test/ui/{issues => associated-types}/issue-25700.rs | 0 src/test/ui/{issues => associated-types}/issue-25700.stderr | 0 src/test/ui/{issues => codegen}/issue-82859-slice-miscompile.rs | 0 src/test/ui/{issues => command}/issue-10626.rs | 0 src/test/ui/{issues => drop}/issue-2734.rs | 0 src/test/ui/{issues => dropck}/issue-34053.rs | 0 src/test/ui/{issues => enum-discriminant}/issue-72554.rs | 0 src/test/ui/{issues => enum-discriminant}/issue-72554.stderr | 0 src/test/ui/{issues => extern}/issue-13655.rs | 0 src/test/ui/{issues => macros}/issue-10536.rs | 0 src/test/ui/{issues => macros}/issue-10536.stderr | 0 src/test/ui/{issues => nll}/issue-54189.rs | 0 src/test/ui/{issues => nll}/issue-54189.stderr | 0 src/test/ui/{issues => traits}/issue-99875.rs | 0 src/test/ui/{issues => traits}/issue-99875.stderr | 0 src/test/ui/{issues => typeck}/issue-18937-1.rs | 0 src/test/ui/{issues => typeck}/issue-18937.rs | 0 src/test/ui/{issues => typeck}/issue-18937.stderr | 0 src/test/ui/{issues => typeck}/issue-31173.rs | 0 src/test/ui/{issues => typeck}/issue-31173.stderr | 0 src/tools/tidy/src/ui_tests.rs | 2 +- 25 files changed, 1 insertion(+), 1 deletion(-) rename src/test/ui/{issues => associated-consts}/issue-105330.rs (100%) rename src/test/ui/{issues => associated-consts}/issue-105330.stderr (100%) rename src/test/ui/{issues => associated-types}/issue-25700-1.rs (100%) rename src/test/ui/{issues => associated-types}/issue-25700-2.rs (100%) rename src/test/ui/{issues => associated-types}/issue-25700.rs (100%) rename src/test/ui/{issues => associated-types}/issue-25700.stderr (100%) rename src/test/ui/{issues => codegen}/issue-82859-slice-miscompile.rs (100%) rename src/test/ui/{issues => command}/issue-10626.rs (100%) rename src/test/ui/{issues => drop}/issue-2734.rs (100%) rename src/test/ui/{issues => dropck}/issue-34053.rs (100%) rename src/test/ui/{issues => enum-discriminant}/issue-72554.rs (100%) rename src/test/ui/{issues => enum-discriminant}/issue-72554.stderr (100%) rename src/test/ui/{issues => extern}/issue-13655.rs (100%) rename src/test/ui/{issues => macros}/issue-10536.rs (100%) rename src/test/ui/{issues => macros}/issue-10536.stderr (100%) rename src/test/ui/{issues => nll}/issue-54189.rs (100%) rename src/test/ui/{issues => nll}/issue-54189.stderr (100%) rename src/test/ui/{issues => traits}/issue-99875.rs (100%) rename src/test/ui/{issues => traits}/issue-99875.stderr (100%) rename src/test/ui/{issues => typeck}/issue-18937-1.rs (100%) rename src/test/ui/{issues => typeck}/issue-18937.rs (100%) rename src/test/ui/{issues => typeck}/issue-18937.stderr (100%) rename src/test/ui/{issues => typeck}/issue-31173.rs (100%) rename src/test/ui/{issues => typeck}/issue-31173.stderr (100%) diff --git a/src/test/ui/issues/issue-105330.rs b/src/test/ui/associated-consts/issue-105330.rs similarity index 100% rename from src/test/ui/issues/issue-105330.rs rename to src/test/ui/associated-consts/issue-105330.rs diff --git a/src/test/ui/issues/issue-105330.stderr b/src/test/ui/associated-consts/issue-105330.stderr similarity index 100% rename from src/test/ui/issues/issue-105330.stderr rename to src/test/ui/associated-consts/issue-105330.stderr diff --git a/src/test/ui/issues/issue-25700-1.rs b/src/test/ui/associated-types/issue-25700-1.rs similarity index 100% rename from src/test/ui/issues/issue-25700-1.rs rename to src/test/ui/associated-types/issue-25700-1.rs diff --git a/src/test/ui/issues/issue-25700-2.rs b/src/test/ui/associated-types/issue-25700-2.rs similarity index 100% rename from src/test/ui/issues/issue-25700-2.rs rename to src/test/ui/associated-types/issue-25700-2.rs diff --git a/src/test/ui/issues/issue-25700.rs b/src/test/ui/associated-types/issue-25700.rs similarity index 100% rename from src/test/ui/issues/issue-25700.rs rename to src/test/ui/associated-types/issue-25700.rs diff --git a/src/test/ui/issues/issue-25700.stderr b/src/test/ui/associated-types/issue-25700.stderr similarity index 100% rename from src/test/ui/issues/issue-25700.stderr rename to src/test/ui/associated-types/issue-25700.stderr diff --git a/src/test/ui/issues/issue-82859-slice-miscompile.rs b/src/test/ui/codegen/issue-82859-slice-miscompile.rs similarity index 100% rename from src/test/ui/issues/issue-82859-slice-miscompile.rs rename to src/test/ui/codegen/issue-82859-slice-miscompile.rs diff --git a/src/test/ui/issues/issue-10626.rs b/src/test/ui/command/issue-10626.rs similarity index 100% rename from src/test/ui/issues/issue-10626.rs rename to src/test/ui/command/issue-10626.rs diff --git a/src/test/ui/issues/issue-2734.rs b/src/test/ui/drop/issue-2734.rs similarity index 100% rename from src/test/ui/issues/issue-2734.rs rename to src/test/ui/drop/issue-2734.rs diff --git a/src/test/ui/issues/issue-34053.rs b/src/test/ui/dropck/issue-34053.rs similarity index 100% rename from src/test/ui/issues/issue-34053.rs rename to src/test/ui/dropck/issue-34053.rs diff --git a/src/test/ui/issues/issue-72554.rs b/src/test/ui/enum-discriminant/issue-72554.rs similarity index 100% rename from src/test/ui/issues/issue-72554.rs rename to src/test/ui/enum-discriminant/issue-72554.rs diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/enum-discriminant/issue-72554.stderr similarity index 100% rename from src/test/ui/issues/issue-72554.stderr rename to src/test/ui/enum-discriminant/issue-72554.stderr diff --git a/src/test/ui/issues/issue-13655.rs b/src/test/ui/extern/issue-13655.rs similarity index 100% rename from src/test/ui/issues/issue-13655.rs rename to src/test/ui/extern/issue-13655.rs diff --git a/src/test/ui/issues/issue-10536.rs b/src/test/ui/macros/issue-10536.rs similarity index 100% rename from src/test/ui/issues/issue-10536.rs rename to src/test/ui/macros/issue-10536.rs diff --git a/src/test/ui/issues/issue-10536.stderr b/src/test/ui/macros/issue-10536.stderr similarity index 100% rename from src/test/ui/issues/issue-10536.stderr rename to src/test/ui/macros/issue-10536.stderr diff --git a/src/test/ui/issues/issue-54189.rs b/src/test/ui/nll/issue-54189.rs similarity index 100% rename from src/test/ui/issues/issue-54189.rs rename to src/test/ui/nll/issue-54189.rs diff --git a/src/test/ui/issues/issue-54189.stderr b/src/test/ui/nll/issue-54189.stderr similarity index 100% rename from src/test/ui/issues/issue-54189.stderr rename to src/test/ui/nll/issue-54189.stderr diff --git a/src/test/ui/issues/issue-99875.rs b/src/test/ui/traits/issue-99875.rs similarity index 100% rename from src/test/ui/issues/issue-99875.rs rename to src/test/ui/traits/issue-99875.rs diff --git a/src/test/ui/issues/issue-99875.stderr b/src/test/ui/traits/issue-99875.stderr similarity index 100% rename from src/test/ui/issues/issue-99875.stderr rename to src/test/ui/traits/issue-99875.stderr diff --git a/src/test/ui/issues/issue-18937-1.rs b/src/test/ui/typeck/issue-18937-1.rs similarity index 100% rename from src/test/ui/issues/issue-18937-1.rs rename to src/test/ui/typeck/issue-18937-1.rs diff --git a/src/test/ui/issues/issue-18937.rs b/src/test/ui/typeck/issue-18937.rs similarity index 100% rename from src/test/ui/issues/issue-18937.rs rename to src/test/ui/typeck/issue-18937.rs diff --git a/src/test/ui/issues/issue-18937.stderr b/src/test/ui/typeck/issue-18937.stderr similarity index 100% rename from src/test/ui/issues/issue-18937.stderr rename to src/test/ui/typeck/issue-18937.stderr diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/typeck/issue-31173.rs similarity index 100% rename from src/test/ui/issues/issue-31173.rs rename to src/test/ui/typeck/issue-31173.rs diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/typeck/issue-31173.stderr similarity index 100% rename from src/test/ui/issues/issue-31173.stderr rename to src/test/ui/typeck/issue-31173.stderr diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 070e72437be8..166d09fa8b06 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -10,7 +10,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 939; -const ISSUES_ENTRY_LIMIT: usize = 2050; +const ISSUES_ENTRY_LIMIT: usize = 1998; fn check_entries(path: &Path, bad: &mut bool) { for dir in Walk::new(&path.join("test/ui")) { From 854082c2189a2b71b661dbe5ac6917c5190bac57 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 4 Jan 2023 12:47:24 -0700 Subject: [PATCH 139/223] docs: fix broken link "search bar" --- library/std/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 13dfd41abbf8..6575cc71b051 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -14,7 +14,7 @@ //! # How to read this documentation //! //! If you already know the name of what you are looking for, the fastest way to -//! find it is to use the search +//! find it is to use the search //! bar at the top of the page. //! //! Otherwise, you may want to jump to one of these useful sections: From 01196c5b4cb3d966aa49ad4ed04bd2ea7aa1f6d2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 4 Jan 2023 13:04:30 -0700 Subject: [PATCH 140/223] rustdoc: remove unnecessary wrapper around sidebar and mobile logos This commit changes `.sidebar a:hover:not(.logo-container)` to add the `:not()` pseudo-class, retaining the old appearance of the logo when mousing over it. This didn't used to be necessary because the `a.sidebar-logo` was `display:inline`, and was what got the `background` changed on hover, while the `div.logo-container` inside it was `display:block`. This resulted in the hover rule not having any effect, because the logo-container box was not actually nested inside the sidebar-logo box: https://www.w3.org/TR/CSS2/visuren.html#anonymous-block-level > When an inline box contains an in-flow block-level box, the inline box (and its inline ancestors within the same line box) are broken around the block-level box (and any block-level siblings that are consecutive or separated only by collapsible whitespace and/or out-of-flow elements), splitting the inline box into two boxes (even if either side is empty), one on each side of the block-level box(es). The line boxes before the break and after the break are enclosed in anonymous block boxes, and the block-level box becomes a sibling of those anonymous boxes. When such an inline box is affected by relative positioning, any resulting translation also affects the block-level box contained in the inline box. --- src/librustdoc/html/static/css/rustdoc.css | 5 ++-- src/librustdoc/html/templates/page.html | 28 ++++++++++------------ 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index afc369bc3fda..cdc077e26bf2 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -352,6 +352,7 @@ img { .sub-logo-container, .logo-container { /* zero text boxes so that computed line height = image height exactly */ line-height: 0; + display: block; } .sub-logo-container { @@ -495,7 +496,7 @@ ul.block, .block li { color: var(--sidebar-link-color); } .sidebar .current, -.sidebar a:hover { +.sidebar a:hover:not(.logo-container) { background-color: var(--sidebar-current-link-background-color); } @@ -1570,7 +1571,7 @@ in storage.js /* Hide the logo and item name from the sidebar. Those are displayed in the mobile-topbar instead. */ - .sidebar .sidebar-logo, + .sidebar .logo-container, .sidebar .location { display: none; } diff --git a/src/librustdoc/html/templates/page.html b/src/librustdoc/html/templates/page.html index bcaff957af2f..fddda293b9a8 100644 --- a/src/librustdoc/html/templates/page.html +++ b/src/librustdoc/html/templates/page.html @@ -72,28 +72,24 @@ {%- if page.css_class != "source" -%} {#- -#} {%- endif -%}
/// - /// If the included file is parsed as an expression, it is placed in the surrounding code - /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). This - /// could result in variables or functions being different from what the file expected if there - /// are variables or functions that have the same name in the current file. + /// The included file is placed in the surrounding code + /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). If + /// the included file is parsed as an expression and variables or functions share names across + /// both files, it could result in variables or functions being different from what the + /// included file expected. /// /// The included file is located relative to the current file (similarly to how modules are /// found). The provided path is interpreted in a platform-specific way at compile time. So, From ea43eb3721e9a6567ff402db442fc5c1ad942009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Jan 2023 16:23:08 -0800 Subject: [PATCH 151/223] Point at expressions where inference refines an unexpected type Address #106355. --- compiler/rustc_hir_typeck/src/demand.rs | 162 +++++++++++++++++- .../two-mismatch-notes.stderr | 2 + .../dont-suggest-missing-await.stderr | 2 + .../suggest-missing-await-closure.stderr | 2 + .../async-await/suggest-missing-await.stderr | 2 + .../closure-return-type-mismatch.stderr | 2 + src/test/ui/coercion/coerce-to-bang.stderr | 9 + .../collections-project-default.stderr | 3 + src/test/ui/issues/issue-15783.stderr | 2 + .../ui/let-else/let-else-ref-bindings.stderr | 12 ++ ...e-trait-object-with-separate-params.stderr | 15 ++ src/test/ui/mismatched_types/abridged.stderr | 36 ++-- .../struct-literal-variant-in-if.stderr | 2 + ...e-does-not-interact-with-let-chains.stderr | 12 ++ src/test/ui/span/coerce-suggestions.stderr | 5 +- src/test/ui/span/issue-33884.stderr | 5 +- .../ui/structs/struct-base-wrong-type.stderr | 2 + src/test/ui/suggestions/call-boxed.stderr | 5 +- ...gest-deref-inside-macro-issue-58298.stderr | 5 +- .../issue-86100-tuple-paren-comma.stderr | 2 + src/test/ui/traits/issue-52893.stderr | 2 + src/test/ui/tuple/wrong_argument_ice-3.stderr | 3 + .../type/type-check/assignment-in-if.stderr | 18 ++ .../type/type-mismatch-same-crate-name.stderr | 6 + 24 files changed, 299 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9c6c53abf074..c9ee5c6cac8b 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -4,6 +4,7 @@ use rustc_errors::MultiSpan; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def::CtorKind; +use rustc_hir::intravisit::Visitor; use rustc_hir::lang_items::LangItem; use rustc_hir::{is_range_literal, Node}; use rustc_infer::infer::InferOk; @@ -11,8 +12,11 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut}; +use rustc_middle::ty::fold::TypeFolder; +use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; +use rustc_middle::ty::{ + self, Article, AssocItem, Ty, TyCtxt, TypeAndMut, TypeSuperFoldable, TypeVisitable, +}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -53,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) - || self.suggest_floating_point_literal(err, expr, expected); + || self.suggest_floating_point_literal(err, expr, expected) + || self.point_inference_types(err, expr); } pub fn emit_coerce_suggestions( @@ -205,6 +210,157 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, Some(err)) } + fn point_inference_types(&self, err: &mut Diagnostic, expr: &hir::Expr<'_>) -> bool { + let tcx = self.tcx; + let map = self.tcx.hir(); + + // Hack to make equality checks on types with inference variables and regions useful. + struct TypeEraser<'tcx> { + tcx: TyCtxt<'tcx>, + } + impl<'tcx> TypeFolder<'tcx> for TypeEraser<'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } + fn fold_region(&mut self, _r: ty::Region<'tcx>) -> ty::Region<'tcx> { + self.tcx().lifetimes.re_erased + } + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + if !t.needs_infer() && !t.has_erasable_regions() { + return t; + } + match *t.kind() { + ty::Infer(ty::TyVar(_) | ty::FreshTy(_)) => { + self.tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))) + } + ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => { + self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 })) + } + ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => { + self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 })) + } + _ => t.super_fold_with(self), + } + } + fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { + ct.super_fold_with(self) + } + } + + let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; }; + let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; }; + let hir::def::Res::Local(hir_id) = p.res else { return false; }; + let Some(node) = map.find(hir_id) else { return false; }; + let hir::Node::Pat(pat) = node else { return false; }; + let parent = map.get_parent_node(pat.hir_id); + let Some(hir::Node::Local(hir::Local { + ty: None, + init: Some(init), + .. + })) = map.find(parent) else { return false; }; + + let ty = self.node_ty(init.hir_id); + if ty.is_closure() || init.span.overlaps(expr.span) { + return false; + } + let mut span_labels = vec![( + init.span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + )]; + + // Locate all the usages of the relevant binding. + struct FindExprs<'hir> { + hir_id: hir::HirId, + uses: Vec<&'hir hir::Expr<'hir>>, + } + impl<'v> Visitor<'v> for FindExprs<'v> { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = ex.kind + && let hir::def::Res::Local(hir_id) = path.res + && hir_id == self.hir_id + { + self.uses.push(ex); + } + hir::intravisit::walk_expr(self, ex); + } + } + + let mut expr_finder = FindExprs { hir_id, uses: vec![] }; + let id = map.get_parent_item(hir_id); + let hir_id: hir::HirId = id.into(); + + if let Some(node) = map.find(hir_id) && let Some(body_id) = node.body_id() { + let body = map.body(body_id); + expr_finder.visit_expr(body.value); + let mut eraser = TypeEraser { tcx }; + let mut prev = eraser.fold_ty(ty); + + for ex in expr_finder.uses { + if ex.span.overlaps(expr.span) { break; } + let parent = map.get_parent_node(ex.hir_id); + if let Some(hir::Node::Expr(expr)) + | Some(hir::Node::Stmt(hir::Stmt { + kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr), + .. + })) = &map.find(parent) + && let hir::ExprKind::MethodCall(s, rcvr, args, span) = expr.kind + && rcvr.hir_id == ex.hir_id + { + let ty = if let Ok(m) = self.lookup_method(ty, s, span, expr, rcvr, args) { + // We get the self type from `lookup_method` because the `rcvr` node + // type will not have had any adjustments from the fn arguments. + let ty = m.sig.inputs_and_output[0]; + match ty.kind() { + // Remove one layer of references to account for `&mut self` and + // `&self`, so that we can compare it against the binding. + ty::Ref(_, ty, _) => *ty, + _ => ty, + } + } else { + self.node_ty(rcvr.hir_id) + }; + let ty = eraser.fold_ty(ty); + if ty.references_error() { + break; + } + if ty != prev { + span_labels.push(( + s.ident.span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + )); + prev = ty; + } + } else { + let ty = eraser.fold_ty(self.node_ty(ex.hir_id)); + if ty.references_error() { + break; + } + if ty != prev { + span_labels.push(( + ex.span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + )); + } + prev = ty; + } + if ex.hir_id == expr.hir_id { + // Stop showing spans after the error type was emitted. + break; + } + } + } + for (sp, label) in span_labels { + err.span_label(sp, &label); + } + true + } + fn annotate_expected_due_to_let_ty( &self, err: &mut Diagnostic, diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr index 7873cf964cbb..3ccd399863d5 100644 --- a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr +++ b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr @@ -1,6 +1,8 @@ error[E0308]: arguments to this function are incorrect --> $DIR/two-mismatch-notes.rs:10:5 | +LL | let w = Wrapper::(1isize); + | ------------------------ here the type of `w` is inferred to be `Wrapper` LL | foo(f, w); | ^^^ | diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 627bf05bba2d..6e232dd00642 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/dont-suggest-missing-await.rs:14:18 | +LL | let x = make_u32(); + | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index a5958baffbaf..9f51832365b6 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await-closure.rs:16:18 | +LL | let x = make_u32(); + | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index 1196601ace09..ce4c8edaf74d 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:12:14 | +LL | let x = make_u32(); + | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/closures/closure-return-type-mismatch.stderr b/src/test/ui/closures/closure-return-type-mismatch.stderr index 3a89d30a05d2..d33cf383cbcb 100644 --- a/src/test/ui/closures/closure-return-type-mismatch.stderr +++ b/src/test/ui/closures/closure-return-type-mismatch.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/closure-return-type-mismatch.rs:7:9 | +LL | let a = true; + | ---- here the type of `a` is inferred to be `bool` LL | a | ^ expected `&str`, found `bool` | diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr index 1207dc7e7a2f..d2fd0f788384 100644 --- a/src/test/ui/coercion/coerce-to-bang.stderr +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -33,6 +33,9 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 | +LL | let b = 22; + | -- here the type of `b` is inferred to be `{integer}` +LL | let c = 44; LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. | --- ^ expected `!`, found integer | | @@ -49,6 +52,9 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 | +LL | let b = 22; + | -- here the type of `b` is inferred to be `{integer}` +LL | let c = 44; LL | foo(a, b, c); | --- ^ expected `!`, found integer | | @@ -65,6 +71,9 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 | +LL | let b = 22; + | -- here the type of `b` is inferred to be `{integer}` +LL | let c = 44; LL | foo(a, b, c); | --- ^ expected `!`, found integer | | diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr index 5701017dc347..c11a5acc3524 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.stderr +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -4,6 +4,9 @@ error[E0308]: mismatched types LL | fn floatify_sibling(ints: &C) -> >::Sibling | ------------------------------------ expected `>::Sibling` because of return type ... +LL | let mut res = ::Member::::empty(); + | ------------------------------------------------------- here the type of `res` is inferred to be `<>::Family as CollectionFamily>::Member` +... LL | res | ^^^ expected Collection::Sibling, found CollectionFamily::Member | diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr index 660dfe9ed3d5..74a7c5de7abe 100644 --- a/src/test/ui/issues/issue-15783.stderr +++ b/src/test/ui/issues/issue-15783.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-15783.rs:8:19 | +LL | let x = Some(&[name]); + | ------------- here the type of `x` is inferred to be `Option<_>` LL | let msg = foo(x); | --- ^ expected slice `[&str]`, found array `[&str; 1]` | | diff --git a/src/test/ui/let-else/let-else-ref-bindings.stderr b/src/test/ui/let-else/let-else-ref-bindings.stderr index 56b9e073330a..39b57ceb43d3 100644 --- a/src/test/ui/let-else/let-else-ref-bindings.stderr +++ b/src/test/ui/let-else/let-else-ref-bindings.stderr @@ -19,6 +19,12 @@ LL | let Some(ref a): Option<&[u8]> = &some else { return }; error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:24:34 | +LL | let some = Some(bytes); + | ----------- here the type of `some` is inferred to be `Option<_>` +... +LL | let Some(ref a): Option<&[u8]> = some else { return }; + | ---- here the type of `some` is inferred to be `Option>` +... LL | let Some(a): Option<&[u8]> = some else { return }; | ------------- ^^^^ expected `&[u8]`, found struct `Vec` | | @@ -59,6 +65,12 @@ LL | let Some(ref mut a): Option<&mut [u8]> = &mut some else { return }; error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:52:38 | +LL | let mut some = Some(bytes); + | ----------- here the type of `some` is inferred to be `Option<_>` +... +LL | let Some(ref mut a): Option<&mut [u8]> = some else { return }; + | ---- here the type of `some` is inferred to be `Option>` +... LL | let Some(a): Option<&mut [u8]> = some else { return }; | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec` | | diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index 82addab94792..1d836f200127 100644 --- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -10,6 +10,9 @@ LL | #![feature(unsized_locals, unsized_fn_params)] error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24 | +LL | let z = x.foo(); + | ------- here the type of `z` is inferred to be `u32` +... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | @@ -18,6 +21,9 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:104:24 | +LL | let z = x.foo(); + | ------- here the type of `z` is inferred to be `u64` +... LL | let _seetype: () = z; | -- ^ expected `()`, found `u64` | | @@ -60,6 +66,9 @@ LL | let z = FinalFoo::foo(x); error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 | +LL | let z = x.foo(); + | ------- here the type of `z` is inferred to be `u8` +... LL | let _seetype: () = z; | -- ^ expected `()`, found `u8` | | @@ -68,6 +77,9 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:157:24 | +LL | let z = x.foo(); + | ------- here the type of `z` is inferred to be `u32` +... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | @@ -76,6 +88,9 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:174:24 | +LL | let z = x.foo(); + | ------- here the type of `z` is inferred to be `u32` +... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index ff1a836c9aec..8fd3239e8ee2 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -53,11 +53,19 @@ LL | Ok(Foo { bar: 1 }) error[E0308]: mismatched types --> $DIR/abridged.rs:39:5 | -LL | fn d() -> X, String> { - | ---------------------------- expected `X, String>` because of return type -... -LL | x - | ^ expected struct `String`, found integer +LL | fn d() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +LL | let x = X { + | _____________- +LL | | x: X { +LL | | x: "".to_string(), +LL | | y: 2, +LL | | }, +LL | | y: 3, +LL | | }; + | |_____- here the type of `x` is inferred to be `X<_, _>` +LL | x + | ^ expected struct `String`, found integer | = note: expected struct `X, String>` found struct `X, {integer}>` @@ -65,11 +73,19 @@ LL | x error[E0308]: mismatched types --> $DIR/abridged.rs:50:5 | -LL | fn e() -> X, String> { - | ---------------------------- expected `X, String>` because of return type -... -LL | x - | ^ expected struct `String`, found integer +LL | fn e() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +LL | let x = X { + | _____________- +LL | | x: X { +LL | | x: "".to_string(), +LL | | y: 2, +LL | | }, +LL | | y: "".to_string(), +LL | | }; + | |_____- here the type of `x` is inferred to be `X<_, _>` +LL | x + | ^ expected struct `String`, found integer | = note: expected struct `X, _>` found struct `X, _>` diff --git a/src/test/ui/parser/struct-literal-variant-in-if.stderr b/src/test/ui/parser/struct-literal-variant-in-if.stderr index 9f0c0074d674..97cdd130d0be 100644 --- a/src/test/ui/parser/struct-literal-variant-in-if.stderr +++ b/src/test/ui/parser/struct-literal-variant-in-if.stderr @@ -51,6 +51,8 @@ LL | if x == E::V { field } {} error[E0308]: mismatched types --> $DIR/struct-literal-variant-in-if.rs:10:20 | +LL | let field = true; + | ---- here the type of `field` is inferred to be `bool` LL | if x == E::V { field } {} | ---------------^^^^^-- | | | diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr index 498a112fa9bb..1785c31cfb94 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -100,6 +100,12 @@ LL | let Some(n) = opt && let another = n else { error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19 | +LL | let opt = Some(1i32); + | ---------- here the type of `opt` is inferred to be `Option<_>` +LL | +LL | let Some(n) = opt else { + | --- here the type of `opt` is inferred to be `Option` +... LL | let Some(n) = opt && n == 1 else { | ^^^ expected `bool`, found enum `Option` | @@ -120,6 +126,12 @@ LL | let Some(n) = opt && n == 1 else { error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 | +LL | let opt = Some(1i32); + | ---------- here the type of `opt` is inferred to be `Option<_>` +LL | +LL | let Some(n) = opt else { + | --- here the type of `opt` is inferred to be `Option` +... LL | let Some(n) = opt && let another = n else { | ^^^ expected `bool`, found enum `Option` | diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index db784d5fe6cf..75d460d7d8ca 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -63,7 +63,10 @@ error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 | LL | s = format!("foo"); - | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String` + | ^^^^^^^^^^^^^^ + | | + | expected `&mut String`, found struct `String` + | here the type of `res` is inferred to be `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index aee153085177..30e248f381c6 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/issue-33884.rs:6:22 | LL | stream.write_fmt(format!("message received")) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected struct `Arguments`, found struct `String` + | here the type of `res` is inferred to be `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/structs/struct-base-wrong-type.stderr b/src/test/ui/structs/struct-base-wrong-type.stderr index b039ce2cc920..30feb9cdd70c 100644 --- a/src/test/ui/structs/struct-base-wrong-type.stderr +++ b/src/test/ui/structs/struct-base-wrong-type.stderr @@ -13,6 +13,8 @@ LL | static foo_i: Foo = Foo { a: 2, ..4 }; error[E0308]: mismatched types --> $DIR/struct-base-wrong-type.rs:12:27 | +LL | let b = Bar { x: 5 }; + | ------------ here the type of `b` is inferred to be `Bar` LL | let f = Foo { a: 2, ..b }; | ^ expected struct `Foo`, found struct `Bar` diff --git a/src/test/ui/suggestions/call-boxed.stderr b/src/test/ui/suggestions/call-boxed.stderr index 9b619ac9a3f5..8295e010f400 100644 --- a/src/test/ui/suggestions/call-boxed.stderr +++ b/src/test/ui/suggestions/call-boxed.stderr @@ -4,7 +4,10 @@ error[E0308]: mismatched types LL | let mut x = 1i32; | ---- expected due to this value LL | let y = Box::new(|| 1); - | -- the found closure + | -------------- + | | | + | | the found closure + | here the type of `y` is inferred to be `Box<_>` LL | x = y; | ^ expected `i32`, found struct `Box` | diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index 5dc4e64446fb..2546f2515d74 100644 --- a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -4,7 +4,10 @@ error[E0308]: mismatched types LL | / intrinsic_match! { LL | | "abc" LL | | }; - | |_____^ expected `&str`, found struct `String` + | | ^ + | | | + | |_____expected `&str`, found struct `String` + | here the type of `res` is inferred to be `String` | = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr index 8c9a41a20276..388d8d8d895e 100644 --- a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr +++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr @@ -49,6 +49,8 @@ LL | let _s = S { _s: ("abc".to_string(),) }; error[E0308]: mismatched types --> $DIR/issue-86100-tuple-paren-comma.rs:23:22 | +LL | let t = (1, 2); + | ------ here the type of `t` is inferred to be `({integer}, {integer})` LL | let _x: (i32,) = (t); | ------ ^^^ expected a tuple with 1 element, found one with 2 elements | | diff --git a/src/test/ui/traits/issue-52893.stderr b/src/test/ui/traits/issue-52893.stderr index 7924d3db06f3..f7b5b7fca06e 100644 --- a/src/test/ui/traits/issue-52893.stderr +++ b/src/test/ui/traits/issue-52893.stderr @@ -4,6 +4,8 @@ error[E0308]: mismatched types LL | impl AddClass for Class

| - this type parameter ... +LL | let output = builder.to_ref(); + | ---------------- here the type of `output` is inferred to be `Class

` LL | builder.push(output); | ---- ^^^^^^ expected type parameter `F`, found struct `Class` | | diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr index 0a503e1fe58c..c83bc28d8553 100644 --- a/src/test/ui/tuple/wrong_argument_ice-3.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr @@ -1,6 +1,9 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied --> $DIR/wrong_argument_ice-3.rs:9:16 | +LL | let new_group = vec![String::new()]; + | ------------------- here the type of `new_group` is inferred to be `Vec<_, _>` +... LL | groups.push(new_group, vec![process]); | ^^^^ ------------- argument of type `Vec<&Process>` unexpected | diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index 9f4558adab15..fb11d6160bba 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -67,6 +67,12 @@ LL | x == 5 error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:44:18 | +LL | let x = 1; + | - here the type of `x` is inferred to be `{integer}` +... +LL | println!("{}", x); + | - here the type of `x` is inferred to be `usize` +... LL | if x == x && x = x && x == x { | ------ ^ expected `bool`, found `usize` | | @@ -75,6 +81,12 @@ LL | if x == x && x = x && x == x { error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:44:22 | +LL | let x = 1; + | - here the type of `x` is inferred to be `{integer}` +... +LL | println!("{}", x); + | - here the type of `x` is inferred to be `usize` +... LL | if x == x && x = x && x == x { | ^ expected `bool`, found `usize` @@ -92,6 +104,12 @@ LL | if x == x && x == x && x == x { error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:51:28 | +LL | let x = 1; + | - here the type of `x` is inferred to be `{integer}` +... +LL | println!("{}", x); + | - here the type of `x` is inferred to be `usize` +... LL | if x == x && x == x && x = x { | ---------------- ^ expected `bool`, found `usize` | | diff --git a/src/test/ui/type/type-mismatch-same-crate-name.stderr b/src/test/ui/type/type-mismatch-same-crate-name.stderr index fcafd315ebf5..e99d30d33963 100644 --- a/src/test/ui/type/type-mismatch-same-crate-name.stderr +++ b/src/test/ui/type/type-mismatch-same-crate-name.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:16:20 | +LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; + | ------------------------------------ here the type of `foo2` is inferred to be `_` +... LL | a::try_foo(foo2); | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo` | | @@ -27,6 +30,9 @@ LL | pub fn try_foo(x: Foo){} error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:20:20 | +LL | let bar2 = {extern crate crate_a2 as a; a::bar()}; + | -------------------------------------- here the type of `bar2` is inferred to be `_` +... LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` | | From 05c30b0ca5450b2beec0a6e4e034953e216f6bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Jan 2023 21:56:19 -0800 Subject: [PATCH 152/223] Skip macros to avoid talking about bindings the user can't see --- compiler/rustc_hir_typeck/src/demand.rs | 2 +- src/test/ui/span/coerce-suggestions.stderr | 5 +---- src/test/ui/span/issue-33884.stderr | 5 +---- .../dont-suggest-deref-inside-macro-issue-58298.stderr | 5 +---- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index c9ee5c6cac8b..5ba0d41ab9d1 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -260,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })) = map.find(parent) else { return false; }; let ty = self.node_ty(init.hir_id); - if ty.is_closure() || init.span.overlaps(expr.span) { + if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() { return false; } let mut span_labels = vec![( diff --git a/src/test/ui/span/coerce-suggestions.stderr b/src/test/ui/span/coerce-suggestions.stderr index 75d460d7d8ca..db784d5fe6cf 100644 --- a/src/test/ui/span/coerce-suggestions.stderr +++ b/src/test/ui/span/coerce-suggestions.stderr @@ -63,10 +63,7 @@ error[E0308]: mismatched types --> $DIR/coerce-suggestions.rs:21:9 | LL | s = format!("foo"); - | ^^^^^^^^^^^^^^ - | | - | expected `&mut String`, found struct `String` - | here the type of `res` is inferred to be `String` + | ^^^^^^^^^^^^^^ expected `&mut String`, found struct `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/span/issue-33884.stderr b/src/test/ui/span/issue-33884.stderr index 30e248f381c6..aee153085177 100644 --- a/src/test/ui/span/issue-33884.stderr +++ b/src/test/ui/span/issue-33884.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-33884.rs:6:22 | LL | stream.write_fmt(format!("message received")) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | expected struct `Arguments`, found struct `String` - | here the type of `res` is inferred to be `String` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Arguments`, found struct `String` | = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr index 2546f2515d74..5dc4e64446fb 100644 --- a/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr +++ b/src/test/ui/suggestions/dont-suggest-deref-inside-macro-issue-58298.stderr @@ -4,10 +4,7 @@ error[E0308]: mismatched types LL | / intrinsic_match! { LL | | "abc" LL | | }; - | | ^ - | | | - | |_____expected `&str`, found struct `String` - | here the type of `res` is inferred to be `String` + | |_____^ expected `&str`, found struct `String` | = note: this error originates in the macro `format` which comes from the expansion of the macro `intrinsic_match` (in Nightly builds, run with -Z macro-backtrace for more info) From 48094a4a6f53ee3be636b4166a7841505bb7cabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Jan 2023 22:25:50 -0800 Subject: [PATCH 153/223] More eagerly resolve expr `ty`s before writing them This allows the expressions to have more accurate types when showing inference steps. --- compiler/rustc_hir_typeck/src/expr.rs | 1 + src/test/ui/issues/issue-15783.stderr | 2 +- src/test/ui/let-else/let-else-ref-bindings.stderr | 10 ++-------- src/test/ui/mismatched_types/abridged.stderr | 4 ++-- ...t-let-else-does-not-interact-with-let-chains.stderr | 10 ++-------- src/test/ui/suggestions/call-boxed.stderr | 2 +- src/test/ui/tuple/wrong_argument_ice-3.stderr | 2 +- src/test/ui/type/type-mismatch-same-crate-name.stderr | 4 ++-- 8 files changed, 12 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 631749fcc0fa..6ed1bc051a5f 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -234,6 +234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) => self.check_expr_path(qpath, expr, args), _ => self.check_expr_kind(expr, expected), }); + let ty = self.resolve_vars_if_possible(ty); // Warn for non-block expressions with diverging children. match expr.kind { diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr index 74a7c5de7abe..e7fecfebdc8f 100644 --- a/src/test/ui/issues/issue-15783.stderr +++ b/src/test/ui/issues/issue-15783.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/issue-15783.rs:8:19 | LL | let x = Some(&[name]); - | ------------- here the type of `x` is inferred to be `Option<_>` + | ------------- here the type of `x` is inferred to be `Option<&[&str; 1]>` LL | let msg = foo(x); | --- ^ expected slice `[&str]`, found array `[&str; 1]` | | diff --git a/src/test/ui/let-else/let-else-ref-bindings.stderr b/src/test/ui/let-else/let-else-ref-bindings.stderr index 39b57ceb43d3..4c58b2db575d 100644 --- a/src/test/ui/let-else/let-else-ref-bindings.stderr +++ b/src/test/ui/let-else/let-else-ref-bindings.stderr @@ -20,10 +20,7 @@ error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:24:34 | LL | let some = Some(bytes); - | ----------- here the type of `some` is inferred to be `Option<_>` -... -LL | let Some(ref a): Option<&[u8]> = some else { return }; - | ---- here the type of `some` is inferred to be `Option>` + | ----------- here the type of `some` is inferred to be `Option>` ... LL | let Some(a): Option<&[u8]> = some else { return }; | ------------- ^^^^ expected `&[u8]`, found struct `Vec` @@ -66,10 +63,7 @@ error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:52:38 | LL | let mut some = Some(bytes); - | ----------- here the type of `some` is inferred to be `Option<_>` -... -LL | let Some(ref mut a): Option<&mut [u8]> = some else { return }; - | ---- here the type of `some` is inferred to be `Option>` + | ----------- here the type of `some` is inferred to be `Option>` ... LL | let Some(a): Option<&mut [u8]> = some else { return }; | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec` diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 8fd3239e8ee2..9b5f0134f127 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -63,7 +63,7 @@ LL | | y: 2, LL | | }, LL | | y: 3, LL | | }; - | |_____- here the type of `x` is inferred to be `X<_, _>` + | |_____- here the type of `x` is inferred to be `X, {integer}>` LL | x | ^ expected struct `String`, found integer | @@ -83,7 +83,7 @@ LL | | y: 2, LL | | }, LL | | y: "".to_string(), LL | | }; - | |_____- here the type of `x` is inferred to be `X<_, _>` + | |_____- here the type of `x` is inferred to be `X, String>` LL | x | ^ expected struct `String`, found integer | diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr index 1785c31cfb94..8c30f015c5d8 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -101,10 +101,7 @@ error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19 | LL | let opt = Some(1i32); - | ---------- here the type of `opt` is inferred to be `Option<_>` -LL | -LL | let Some(n) = opt else { - | --- here the type of `opt` is inferred to be `Option` + | ---------- here the type of `opt` is inferred to be `Option` ... LL | let Some(n) = opt && n == 1 else { | ^^^ expected `bool`, found enum `Option` @@ -127,10 +124,7 @@ error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 | LL | let opt = Some(1i32); - | ---------- here the type of `opt` is inferred to be `Option<_>` -LL | -LL | let Some(n) = opt else { - | --- here the type of `opt` is inferred to be `Option` + | ---------- here the type of `opt` is inferred to be `Option` ... LL | let Some(n) = opt && let another = n else { | ^^^ expected `bool`, found enum `Option` diff --git a/src/test/ui/suggestions/call-boxed.stderr b/src/test/ui/suggestions/call-boxed.stderr index 8295e010f400..1609c2a3094e 100644 --- a/src/test/ui/suggestions/call-boxed.stderr +++ b/src/test/ui/suggestions/call-boxed.stderr @@ -7,7 +7,7 @@ LL | let y = Box::new(|| 1); | -------------- | | | | | the found closure - | here the type of `y` is inferred to be `Box<_>` + | here the type of `y` is inferred to be `Box<[closure@call-boxed.rs:3:22]>` LL | x = y; | ^ expected `i32`, found struct `Box` | diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr index c83bc28d8553..1ad1d6921210 100644 --- a/src/test/ui/tuple/wrong_argument_ice-3.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr @@ -2,7 +2,7 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied --> $DIR/wrong_argument_ice-3.rs:9:16 | LL | let new_group = vec![String::new()]; - | ------------------- here the type of `new_group` is inferred to be `Vec<_, _>` + | ------------------- here the type of `new_group` is inferred to be `Vec` ... LL | groups.push(new_group, vec![process]); | ^^^^ ------------- argument of type `Vec<&Process>` unexpected diff --git a/src/test/ui/type/type-mismatch-same-crate-name.stderr b/src/test/ui/type/type-mismatch-same-crate-name.stderr index e99d30d33963..0d754459f4a5 100644 --- a/src/test/ui/type/type-mismatch-same-crate-name.stderr +++ b/src/test/ui/type/type-mismatch-same-crate-name.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:16:20 | LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; - | ------------------------------------ here the type of `foo2` is inferred to be `_` + | ------------------------------------ here the type of `foo2` is inferred to be `Foo` ... LL | a::try_foo(foo2); | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo` @@ -31,7 +31,7 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:20:20 | LL | let bar2 = {extern crate crate_a2 as a; a::bar()}; - | -------------------------------------- here the type of `bar2` is inferred to be `_` + | -------------------------------------- here the type of `bar2` is inferred to be `Box` ... LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` From 6b0cce4b5018bcd1c7aed1f84cb0b86e3cc03f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Jan 2023 23:34:26 -0800 Subject: [PATCH 154/223] review comments: do not always point at init expr --- compiler/rustc_hir_typeck/src/demand.rs | 3 ++ .../two-mismatch-notes.stderr | 2 -- .../dont-suggest-missing-await.stderr | 2 -- .../suggest-missing-await-closure.stderr | 2 -- .../async-await/suggest-missing-await.stderr | 2 -- .../closure-return-type-mismatch.stderr | 2 -- src/test/ui/coercion/coerce-to-bang.stderr | 9 ----- .../collections-project-default.stderr | 3 -- src/test/ui/issues/issue-15783.stderr | 2 -- .../ui/let-else/let-else-ref-bindings.stderr | 6 ---- ...e-trait-object-with-separate-params.stderr | 15 -------- src/test/ui/mismatched_types/abridged.stderr | 36 ++++++------------- .../struct-literal-variant-in-if.stderr | 2 -- ...e-does-not-interact-with-let-chains.stderr | 6 ---- .../ui/structs/struct-base-wrong-type.stderr | 2 -- src/test/ui/suggestions/call-boxed.stderr | 5 +-- .../issue-86100-tuple-paren-comma.stderr | 2 -- src/test/ui/traits/issue-52893.stderr | 2 -- src/test/ui/tuple/wrong_argument_ice-3.stderr | 3 -- .../type/type-mismatch-same-crate-name.stderr | 6 ---- 20 files changed, 14 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 5ba0d41ab9d1..c50d03b944ff 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -355,6 +355,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + if span_labels.len() < 2 { + return false; + } for (sp, label) in span_labels { err.span_label(sp, &label); } diff --git a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr index 3ccd399863d5..7873cf964cbb 100644 --- a/src/test/ui/argument-suggestions/two-mismatch-notes.stderr +++ b/src/test/ui/argument-suggestions/two-mismatch-notes.stderr @@ -1,8 +1,6 @@ error[E0308]: arguments to this function are incorrect --> $DIR/two-mismatch-notes.rs:10:5 | -LL | let w = Wrapper::(1isize); - | ------------------------ here the type of `w` is inferred to be `Wrapper` LL | foo(f, w); | ^^^ | diff --git a/src/test/ui/async-await/dont-suggest-missing-await.stderr b/src/test/ui/async-await/dont-suggest-missing-await.stderr index 6e232dd00642..627bf05bba2d 100644 --- a/src/test/ui/async-await/dont-suggest-missing-await.stderr +++ b/src/test/ui/async-await/dont-suggest-missing-await.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/dont-suggest-missing-await.rs:14:18 | -LL | let x = make_u32(); - | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/async-await/suggest-missing-await-closure.stderr b/src/test/ui/async-await/suggest-missing-await-closure.stderr index 9f51832365b6..a5958baffbaf 100644 --- a/src/test/ui/async-await/suggest-missing-await-closure.stderr +++ b/src/test/ui/async-await/suggest-missing-await-closure.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await-closure.rs:16:18 | -LL | let x = make_u32(); - | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/async-await/suggest-missing-await.stderr b/src/test/ui/async-await/suggest-missing-await.stderr index ce4c8edaf74d..1196601ace09 100644 --- a/src/test/ui/async-await/suggest-missing-await.stderr +++ b/src/test/ui/async-await/suggest-missing-await.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/suggest-missing-await.rs:12:14 | -LL | let x = make_u32(); - | ---------- here the type of `x` is inferred to be `impl Future` LL | take_u32(x) | -------- ^ expected `u32`, found opaque type | | diff --git a/src/test/ui/closures/closure-return-type-mismatch.stderr b/src/test/ui/closures/closure-return-type-mismatch.stderr index d33cf383cbcb..3a89d30a05d2 100644 --- a/src/test/ui/closures/closure-return-type-mismatch.stderr +++ b/src/test/ui/closures/closure-return-type-mismatch.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/closure-return-type-mismatch.rs:7:9 | -LL | let a = true; - | ---- here the type of `a` is inferred to be `bool` LL | a | ^ expected `&str`, found `bool` | diff --git a/src/test/ui/coercion/coerce-to-bang.stderr b/src/test/ui/coercion/coerce-to-bang.stderr index d2fd0f788384..1207dc7e7a2f 100644 --- a/src/test/ui/coercion/coerce-to-bang.stderr +++ b/src/test/ui/coercion/coerce-to-bang.stderr @@ -33,9 +33,6 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:26:12 | -LL | let b = 22; - | -- here the type of `b` is inferred to be `{integer}` -LL | let c = 44; LL | foo(a, b, c); // ... and hence a reference to `a` is expected to diverge. | --- ^ expected `!`, found integer | | @@ -52,9 +49,6 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:36:12 | -LL | let b = 22; - | -- here the type of `b` is inferred to be `{integer}` -LL | let c = 44; LL | foo(a, b, c); | --- ^ expected `!`, found integer | | @@ -71,9 +65,6 @@ LL | fn foo(x: usize, y: !, z: usize) { } error[E0308]: mismatched types --> $DIR/coerce-to-bang.rs:45:12 | -LL | let b = 22; - | -- here the type of `b` is inferred to be `{integer}` -LL | let c = 44; LL | foo(a, b, c); | --- ^ expected `!`, found integer | | diff --git a/src/test/ui/generic-associated-types/collections-project-default.stderr b/src/test/ui/generic-associated-types/collections-project-default.stderr index c11a5acc3524..5701017dc347 100644 --- a/src/test/ui/generic-associated-types/collections-project-default.stderr +++ b/src/test/ui/generic-associated-types/collections-project-default.stderr @@ -4,9 +4,6 @@ error[E0308]: mismatched types LL | fn floatify_sibling(ints: &C) -> >::Sibling | ------------------------------------ expected `>::Sibling` because of return type ... -LL | let mut res = ::Member::::empty(); - | ------------------------------------------------------- here the type of `res` is inferred to be `<>::Family as CollectionFamily>::Member` -... LL | res | ^^^ expected Collection::Sibling, found CollectionFamily::Member | diff --git a/src/test/ui/issues/issue-15783.stderr b/src/test/ui/issues/issue-15783.stderr index e7fecfebdc8f..660dfe9ed3d5 100644 --- a/src/test/ui/issues/issue-15783.stderr +++ b/src/test/ui/issues/issue-15783.stderr @@ -1,8 +1,6 @@ error[E0308]: mismatched types --> $DIR/issue-15783.rs:8:19 | -LL | let x = Some(&[name]); - | ------------- here the type of `x` is inferred to be `Option<&[&str; 1]>` LL | let msg = foo(x); | --- ^ expected slice `[&str]`, found array `[&str; 1]` | | diff --git a/src/test/ui/let-else/let-else-ref-bindings.stderr b/src/test/ui/let-else/let-else-ref-bindings.stderr index 4c58b2db575d..56b9e073330a 100644 --- a/src/test/ui/let-else/let-else-ref-bindings.stderr +++ b/src/test/ui/let-else/let-else-ref-bindings.stderr @@ -19,9 +19,6 @@ LL | let Some(ref a): Option<&[u8]> = &some else { return }; error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:24:34 | -LL | let some = Some(bytes); - | ----------- here the type of `some` is inferred to be `Option>` -... LL | let Some(a): Option<&[u8]> = some else { return }; | ------------- ^^^^ expected `&[u8]`, found struct `Vec` | | @@ -62,9 +59,6 @@ LL | let Some(ref mut a): Option<&mut [u8]> = &mut some else { return }; error[E0308]: mismatched types --> $DIR/let-else-ref-bindings.rs:52:38 | -LL | let mut some = Some(bytes); - | ----------- here the type of `some` is inferred to be `Option>` -... LL | let Some(a): Option<&mut [u8]> = some else { return }; | ----------------- ^^^^ expected `&mut [u8]`, found struct `Vec` | | diff --git a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr index 1d836f200127..82addab94792 100644 --- a/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr +++ b/src/test/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr @@ -10,9 +10,6 @@ LL | #![feature(unsized_locals, unsized_fn_params)] error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:87:24 | -LL | let z = x.foo(); - | ------- here the type of `z` is inferred to be `u32` -... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | @@ -21,9 +18,6 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:104:24 | -LL | let z = x.foo(); - | ------- here the type of `z` is inferred to be `u64` -... LL | let _seetype: () = z; | -- ^ expected `()`, found `u64` | | @@ -66,9 +60,6 @@ LL | let z = FinalFoo::foo(x); error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24 | -LL | let z = x.foo(); - | ------- here the type of `z` is inferred to be `u8` -... LL | let _seetype: () = z; | -- ^ expected `()`, found `u8` | | @@ -77,9 +68,6 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:157:24 | -LL | let z = x.foo(); - | ------- here the type of `z` is inferred to be `u32` -... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | @@ -88,9 +76,6 @@ LL | let _seetype: () = z; error[E0308]: mismatched types --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:174:24 | -LL | let z = x.foo(); - | ------- here the type of `z` is inferred to be `u32` -... LL | let _seetype: () = z; | -- ^ expected `()`, found `u32` | | diff --git a/src/test/ui/mismatched_types/abridged.stderr b/src/test/ui/mismatched_types/abridged.stderr index 9b5f0134f127..ff1a836c9aec 100644 --- a/src/test/ui/mismatched_types/abridged.stderr +++ b/src/test/ui/mismatched_types/abridged.stderr @@ -53,19 +53,11 @@ LL | Ok(Foo { bar: 1 }) error[E0308]: mismatched types --> $DIR/abridged.rs:39:5 | -LL | fn d() -> X, String> { - | ---------------------------- expected `X, String>` because of return type -LL | let x = X { - | _____________- -LL | | x: X { -LL | | x: "".to_string(), -LL | | y: 2, -LL | | }, -LL | | y: 3, -LL | | }; - | |_____- here the type of `x` is inferred to be `X, {integer}>` -LL | x - | ^ expected struct `String`, found integer +LL | fn d() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +... +LL | x + | ^ expected struct `String`, found integer | = note: expected struct `X, String>` found struct `X, {integer}>` @@ -73,19 +65,11 @@ LL | x error[E0308]: mismatched types --> $DIR/abridged.rs:50:5 | -LL | fn e() -> X, String> { - | ---------------------------- expected `X, String>` because of return type -LL | let x = X { - | _____________- -LL | | x: X { -LL | | x: "".to_string(), -LL | | y: 2, -LL | | }, -LL | | y: "".to_string(), -LL | | }; - | |_____- here the type of `x` is inferred to be `X, String>` -LL | x - | ^ expected struct `String`, found integer +LL | fn e() -> X, String> { + | ---------------------------- expected `X, String>` because of return type +... +LL | x + | ^ expected struct `String`, found integer | = note: expected struct `X, _>` found struct `X, _>` diff --git a/src/test/ui/parser/struct-literal-variant-in-if.stderr b/src/test/ui/parser/struct-literal-variant-in-if.stderr index 97cdd130d0be..9f0c0074d674 100644 --- a/src/test/ui/parser/struct-literal-variant-in-if.stderr +++ b/src/test/ui/parser/struct-literal-variant-in-if.stderr @@ -51,8 +51,6 @@ LL | if x == E::V { field } {} error[E0308]: mismatched types --> $DIR/struct-literal-variant-in-if.rs:10:20 | -LL | let field = true; - | ---- here the type of `field` is inferred to be `bool` LL | if x == E::V { field } {} | ---------------^^^^^-- | | | diff --git a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr index 8c30f015c5d8..498a112fa9bb 100644 --- a/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/ensure-that-let-else-does-not-interact-with-let-chains.stderr @@ -100,9 +100,6 @@ LL | let Some(n) = opt && let another = n else { error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:9:19 | -LL | let opt = Some(1i32); - | ---------- here the type of `opt` is inferred to be `Option` -... LL | let Some(n) = opt && n == 1 else { | ^^^ expected `bool`, found enum `Option` | @@ -123,9 +120,6 @@ LL | let Some(n) = opt && n == 1 else { error[E0308]: mismatched types --> $DIR/ensure-that-let-else-does-not-interact-with-let-chains.rs:15:19 | -LL | let opt = Some(1i32); - | ---------- here the type of `opt` is inferred to be `Option` -... LL | let Some(n) = opt && let another = n else { | ^^^ expected `bool`, found enum `Option` | diff --git a/src/test/ui/structs/struct-base-wrong-type.stderr b/src/test/ui/structs/struct-base-wrong-type.stderr index 30feb9cdd70c..b039ce2cc920 100644 --- a/src/test/ui/structs/struct-base-wrong-type.stderr +++ b/src/test/ui/structs/struct-base-wrong-type.stderr @@ -13,8 +13,6 @@ LL | static foo_i: Foo = Foo { a: 2, ..4 }; error[E0308]: mismatched types --> $DIR/struct-base-wrong-type.rs:12:27 | -LL | let b = Bar { x: 5 }; - | ------------ here the type of `b` is inferred to be `Bar` LL | let f = Foo { a: 2, ..b }; | ^ expected struct `Foo`, found struct `Bar` diff --git a/src/test/ui/suggestions/call-boxed.stderr b/src/test/ui/suggestions/call-boxed.stderr index 1609c2a3094e..9b619ac9a3f5 100644 --- a/src/test/ui/suggestions/call-boxed.stderr +++ b/src/test/ui/suggestions/call-boxed.stderr @@ -4,10 +4,7 @@ error[E0308]: mismatched types LL | let mut x = 1i32; | ---- expected due to this value LL | let y = Box::new(|| 1); - | -------------- - | | | - | | the found closure - | here the type of `y` is inferred to be `Box<[closure@call-boxed.rs:3:22]>` + | -- the found closure LL | x = y; | ^ expected `i32`, found struct `Box` | diff --git a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr index 388d8d8d895e..8c9a41a20276 100644 --- a/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr +++ b/src/test/ui/suggestions/issue-86100-tuple-paren-comma.stderr @@ -49,8 +49,6 @@ LL | let _s = S { _s: ("abc".to_string(),) }; error[E0308]: mismatched types --> $DIR/issue-86100-tuple-paren-comma.rs:23:22 | -LL | let t = (1, 2); - | ------ here the type of `t` is inferred to be `({integer}, {integer})` LL | let _x: (i32,) = (t); | ------ ^^^ expected a tuple with 1 element, found one with 2 elements | | diff --git a/src/test/ui/traits/issue-52893.stderr b/src/test/ui/traits/issue-52893.stderr index f7b5b7fca06e..7924d3db06f3 100644 --- a/src/test/ui/traits/issue-52893.stderr +++ b/src/test/ui/traits/issue-52893.stderr @@ -4,8 +4,6 @@ error[E0308]: mismatched types LL | impl AddClass for Class

| - this type parameter ... -LL | let output = builder.to_ref(); - | ---------------- here the type of `output` is inferred to be `Class

` LL | builder.push(output); | ---- ^^^^^^ expected type parameter `F`, found struct `Class` | | diff --git a/src/test/ui/tuple/wrong_argument_ice-3.stderr b/src/test/ui/tuple/wrong_argument_ice-3.stderr index 1ad1d6921210..0a503e1fe58c 100644 --- a/src/test/ui/tuple/wrong_argument_ice-3.stderr +++ b/src/test/ui/tuple/wrong_argument_ice-3.stderr @@ -1,9 +1,6 @@ error[E0061]: this method takes 1 argument but 2 arguments were supplied --> $DIR/wrong_argument_ice-3.rs:9:16 | -LL | let new_group = vec![String::new()]; - | ------------------- here the type of `new_group` is inferred to be `Vec` -... LL | groups.push(new_group, vec![process]); | ^^^^ ------------- argument of type `Vec<&Process>` unexpected | diff --git a/src/test/ui/type/type-mismatch-same-crate-name.stderr b/src/test/ui/type/type-mismatch-same-crate-name.stderr index 0d754459f4a5..fcafd315ebf5 100644 --- a/src/test/ui/type/type-mismatch-same-crate-name.stderr +++ b/src/test/ui/type/type-mismatch-same-crate-name.stderr @@ -1,9 +1,6 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:16:20 | -LL | let foo2 = {extern crate crate_a2 as a; a::Foo}; - | ------------------------------------ here the type of `foo2` is inferred to be `Foo` -... LL | a::try_foo(foo2); | ---------- ^^^^ expected struct `main::a::Foo`, found a different struct `main::a::Foo` | | @@ -30,9 +27,6 @@ LL | pub fn try_foo(x: Foo){} error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:20:20 | -LL | let bar2 = {extern crate crate_a2 as a; a::bar()}; - | -------------------------------------- here the type of `bar2` is inferred to be `Box` -... LL | a::try_bar(bar2); | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` | | From 9cc8d8619062278046e678bbc08401b733a17236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Jan 2023 20:20:31 -0800 Subject: [PATCH 155/223] Tweak output - Only point at a the single expression where the found type was first inferred. - Find method call argument that might have caused the found type to be inferred. - Provide structured suggestion. - Apply some review comments. - Tweak wording. --- compiler/rustc_hir_typeck/src/demand.rs | 167 +++++++++++++----- .../type/type-check/assignment-in-if.stderr | 15 +- .../type/type-check/point-at-inference-2.rs | 13 ++ .../type-check/point-at-inference-2.stderr | 56 ++++++ .../type/type-check/point-at-inference.fixed | 13 ++ .../ui/type/type-check/point-at-inference.rs | 13 ++ .../type/type-check/point-at-inference.stderr | 26 +++ 7 files changed, 243 insertions(+), 60 deletions(-) create mode 100644 src/test/ui/type/type-check/point-at-inference-2.rs create mode 100644 src/test/ui/type/type-check/point-at-inference-2.stderr create mode 100644 src/test/ui/type/type-check/point-at-inference.fixed create mode 100644 src/test/ui/type/type-check/point-at-inference.rs create mode 100644 src/test/ui/type/type-check/point-at-inference.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index c50d03b944ff..317e9b5a7a1e 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,5 +1,6 @@ use crate::FnCtxt; use rustc_ast::util::parser::PREC_POSTFIX; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::MultiSpan; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir as hir; @@ -14,12 +15,14 @@ use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::TypeFolder; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; +use rustc_middle::ty::relate::TypeRelation; use rustc_middle::ty::{ self, Article, AssocItem, Ty, TyCtxt, TypeAndMut, TypeSuperFoldable, TypeVisitable, }; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::error_reporting::method_chain::CollectAllMismatches; use rustc_trait_selection::traits::ObligationCause; use super::method::probe; @@ -44,7 +47,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.annotate_alternative_method_deref(err, expr, error); // Use `||` to give these suggestions a precedence - let _ = self.suggest_missing_parentheses(err, expr) + let suggested = self.suggest_missing_parentheses(err, expr) || self.suggest_remove_last_method_call(err, expr, expected) || self.suggest_associated_const(err, expr, expected) || self.suggest_deref_ref_or_into(err, expr, expected, expr_ty, expected_ty_expr) @@ -57,8 +60,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) - || self.suggest_floating_point_literal(err, expr, expected) - || self.point_inference_types(err, expr); + || self.suggest_floating_point_literal(err, expr, expected); + if !suggested { + self.point_at_expr_source_of_inferred_type(err, expr, expr_ty, expected); + } } pub fn emit_coerce_suggestions( @@ -210,7 +215,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, Some(err)) } - fn point_inference_types(&self, err: &mut Diagnostic, expr: &hir::Expr<'_>) -> bool { + fn point_at_expr_source_of_inferred_type( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + found: Ty<'tcx>, + expected: Ty<'tcx>, + ) -> bool { let tcx = self.tcx; let map = self.tcx.hir(); @@ -250,25 +261,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; }; let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; }; let hir::def::Res::Local(hir_id) = p.res else { return false; }; - let Some(node) = map.find(hir_id) else { return false; }; - let hir::Node::Pat(pat) = node else { return false; }; + let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; }; let parent = map.get_parent_node(pat.hir_id); let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. })) = map.find(parent) else { return false; }; - - let ty = self.node_ty(init.hir_id); + let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; }; if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() { return false; } - let mut span_labels = vec![( - init.span, - with_forced_trimmed_paths!(format!( - "here the type of `{ident}` is inferred to be `{ty}`", - )), - )]; // Locate all the usages of the relevant binding. struct FindExprs<'hir> { @@ -296,71 +299,139 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_finder.visit_expr(body.value); let mut eraser = TypeEraser { tcx }; let mut prev = eraser.fold_ty(ty); + let mut prev_span = None; - for ex in expr_finder.uses { - if ex.span.overlaps(expr.span) { break; } - let parent = map.get_parent_node(ex.hir_id); + for binding in expr_finder.uses { + // In every expression where the binding is referenced, we will look at that + // expression's type and see if it is where the incorrect found type was fully + // "materialized" and point at it. We will also try to provide a suggestion there. + let parent = map.get_parent_node(binding.hir_id); if let Some(hir::Node::Expr(expr)) | Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr), .. })) = &map.find(parent) - && let hir::ExprKind::MethodCall(s, rcvr, args, span) = expr.kind - && rcvr.hir_id == ex.hir_id + && let hir::ExprKind::MethodCall(s, rcvr, args, _span) = expr.kind + && rcvr.hir_id == binding.hir_id + && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id) { - let ty = if let Ok(m) = self.lookup_method(ty, s, span, expr, rcvr, args) { - // We get the self type from `lookup_method` because the `rcvr` node - // type will not have had any adjustments from the fn arguments. - let ty = m.sig.inputs_and_output[0]; - match ty.kind() { - // Remove one layer of references to account for `&mut self` and - // `&self`, so that we can compare it against the binding. - ty::Ref(_, ty, _) => *ty, - _ => ty, - } - } else { - self.node_ty(rcvr.hir_id) + // We special case methods, because they can influence inference through the + // call's arguments and we can provide a more explicit span. + let sig = self.tcx.fn_sig(def_id); + let def_self_ty = sig.input(0).skip_binder(); + let rcvr_ty = self.node_ty(rcvr.hir_id); + // Get the evaluated type *after* calling the method call, so that the influence + // of the arguments can be reflected in the receiver type. The receiver + // expression has the type *before* theis analysis is done. + let ty = match self.lookup_probe(s.ident, rcvr_ty, expr, probe::ProbeScope::TraitsInScope) { + Ok(pick) => pick.self_ty, + Err(_) => rcvr_ty, }; + // Remove one layer of references to account for `&mut self` and + // `&self`, so that we can compare it against the binding. + let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) { + (ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty), + _ => (ty, def_self_ty), + }; + let mut param_args = FxHashMap::default(); + let mut param_expected = FxHashMap::default(); + let mut param_found = FxHashMap::default(); + if self.can_eq(self.param_env, ty, found).is_ok() { + // We only point at the first place where the found type was inferred. + for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() { + if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() { + // We found an argument that references a type parameter in `Self`, + // so we assume that this is the argument that caused the found + // type, which we know already because of `can_eq` above was first + // inferred in this method call. + let arg = &args[i]; + let arg_ty = self.node_ty(arg.hir_id); + err.span_label( + arg.span, + &format!( + "this is of type `{arg_ty}`, which makes `{ident}` to be \ + inferred as `{ty}`", + ), + ); + param_args.insert(param_ty, (arg, arg_ty)); + } + } + } + + // Here we find, for a type param `T`, the type that `T` is in the current + // method call *and* in the original expected type. That way, we can see if we + // can give any structured suggestion for the function argument. + let mut c = CollectAllMismatches { + infcx: &self.infcx, + param_env: self.param_env, + errors: vec![], + }; + let _ = c.relate(def_self_ty, ty); + for error in c.errors { + if let TypeError::Sorts(error) = error { + param_found.insert(error.expected, error.found); + } + } + c.errors = vec![]; + let _ = c.relate(def_self_ty, expected); + for error in c.errors { + if let TypeError::Sorts(error) = error { + param_expected.insert(error.expected, error.found); + } + } + for (param, (arg,arg_ty)) in param_args.iter() { + let Some(expected) = param_expected.get(param) else { continue; }; + let Some(found) = param_found.get(param) else { continue; }; + if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; } + self.suggest_deref_ref_or_into(err, arg, *expected, *found, None); + } + let ty = eraser.fold_ty(ty); if ty.references_error() { break; } - if ty != prev { - span_labels.push(( + if ty != prev + && param_args.is_empty() + && self.can_eq(self.param_env, ty, found).is_ok() + { + // We only point at the first place where the found type was inferred. + err.span_label( s.ident.span, with_forced_trimmed_paths!(format!( "here the type of `{ident}` is inferred to be `{ty}`", )), - )); - prev = ty; + ); + break; } + prev = ty; } else { - let ty = eraser.fold_ty(self.node_ty(ex.hir_id)); + let ty = eraser.fold_ty(self.node_ty(binding.hir_id)); if ty.references_error() { break; } - if ty != prev { - span_labels.push(( - ex.span, + if ty != prev && let Some(span) = prev_span && self.can_eq(self.param_env, ty, found).is_ok() { + // We only point at the first place where the found type was inferred. + // We use the *previous* span because if the type is known *here* it means + // it was *evaluated earlier*. We don't do this for method calls because we + // evaluate the method's self type eagerly, but not in any other case. + err.span_label( + span, with_forced_trimmed_paths!(format!( "here the type of `{ident}` is inferred to be `{ty}`", )), - )); + ); + break; } prev = ty; } - if ex.hir_id == expr.hir_id { - // Stop showing spans after the error type was emitted. + if binding.hir_id == expr.hir_id { + // Do not look at expressions that come after the expression we were originally + // evaluating and had a type error. break; } + prev_span = Some(binding.span); } } - if span_labels.len() < 2 { - return false; - } - for (sp, label) in span_labels { - err.span_label(sp, &label); - } true } diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr index fb11d6160bba..de133e5599cf 100644 --- a/src/test/ui/type/type-check/assignment-in-if.stderr +++ b/src/test/ui/type/type-check/assignment-in-if.stderr @@ -67,10 +67,7 @@ LL | x == 5 error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:44:18 | -LL | let x = 1; - | - here the type of `x` is inferred to be `{integer}` -... -LL | println!("{}", x); +LL | if y = (Foo { foo: x }) { | - here the type of `x` is inferred to be `usize` ... LL | if x == x && x = x && x == x { @@ -81,10 +78,7 @@ LL | if x == x && x = x && x == x { error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:44:22 | -LL | let x = 1; - | - here the type of `x` is inferred to be `{integer}` -... -LL | println!("{}", x); +LL | if y = (Foo { foo: x }) { | - here the type of `x` is inferred to be `usize` ... LL | if x == x && x = x && x == x { @@ -104,10 +98,7 @@ LL | if x == x && x == x && x == x { error[E0308]: mismatched types --> $DIR/assignment-in-if.rs:51:28 | -LL | let x = 1; - | - here the type of `x` is inferred to be `{integer}` -... -LL | println!("{}", x); +LL | if y = (Foo { foo: x }) { | - here the type of `x` is inferred to be `usize` ... LL | if x == x && x == x && x = x { diff --git a/src/test/ui/type/type-check/point-at-inference-2.rs b/src/test/ui/type/type-check/point-at-inference-2.rs new file mode 100644 index 000000000000..6557d7fa1911 --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference-2.rs @@ -0,0 +1,13 @@ +fn bar(_: Vec) {} +fn baz(_: &Vec<&i32>) {} +fn main() { + let v = vec![&1]; + bar(v); //~ ERROR E0308 + let v = vec![]; + baz(&v); + baz(&v); + bar(v); //~ ERROR E0308 + let v = vec![]; + baz(&v); + bar(v); //~ ERROR E0308 +} diff --git a/src/test/ui/type/type-check/point-at-inference-2.stderr b/src/test/ui/type/type-check/point-at-inference-2.stderr new file mode 100644 index 000000000000..13227c5e245b --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference-2.stderr @@ -0,0 +1,56 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:5:9 + | +LL | bar(v); + | --- ^ expected `i32`, found `&{integer}` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&{integer}>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:9:9 + | +LL | baz(&v); + | - here the type of `v` is inferred to be `Vec<&i32>` +LL | baz(&v); +LL | bar(v); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&i32>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error[E0308]: mismatched types + --> $DIR/point-at-inference-2.rs:12:9 + | +LL | baz(&v); + | - here the type of `v` is inferred to be `Vec<&i32>` +LL | bar(v); + | --- ^ expected `i32`, found `&i32` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&i32>` +note: function defined here + --> $DIR/point-at-inference-2.rs:1:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/type/type-check/point-at-inference.fixed b/src/test/ui/type/type-check/point-at-inference.fixed new file mode 100644 index 000000000000..f41fbe59fba6 --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference.fixed @@ -0,0 +1,13 @@ +// run-rustfix +fn bar(_: Vec) {} +fn baz(_: &impl std::any::Any) {} +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let mut foo = vec![]; + baz(&foo); + for i in &v { + foo.push(*i); + } + baz(&foo); + bar(foo); //~ ERROR E0308 +} diff --git a/src/test/ui/type/type-check/point-at-inference.rs b/src/test/ui/type/type-check/point-at-inference.rs new file mode 100644 index 000000000000..6419e42e70d1 --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference.rs @@ -0,0 +1,13 @@ +// run-rustfix +fn bar(_: Vec) {} +fn baz(_: &impl std::any::Any) {} +fn main() { + let v = vec![1, 2, 3, 4, 5]; + let mut foo = vec![]; + baz(&foo); + for i in &v { + foo.push(i); + } + baz(&foo); + bar(foo); //~ ERROR E0308 +} diff --git a/src/test/ui/type/type-check/point-at-inference.stderr b/src/test/ui/type/type-check/point-at-inference.stderr new file mode 100644 index 000000000000..197511bf64ef --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference.stderr @@ -0,0 +1,26 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference.rs:12:9 + | +LL | foo.push(i); + | - this is of type `&{integer}`, which makes `foo` to be inferred as `Vec<&{integer}>` +... +LL | bar(foo); + | --- ^^^ expected `i32`, found `&{integer}` + | | + | arguments to this function are incorrect + | + = note: expected struct `Vec` + found struct `Vec<&{integer}>` +note: function defined here + --> $DIR/point-at-inference.rs:2:4 + | +LL | fn bar(_: Vec) {} + | ^^^ ----------- +help: consider dereferencing the borrow + | +LL | foo.push(*i); + | + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 4ac7d1c3ab519c72bf10521f0675060b12b0bb0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Jan 2023 20:32:15 -0800 Subject: [PATCH 156/223] Formatting --- compiler/rustc_hir_typeck/src/demand.rs | 268 ++++++++++++------------ 1 file changed, 138 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 317e9b5a7a1e..41bbe2d15c16 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -294,143 +294,151 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let id = map.get_parent_item(hir_id); let hir_id: hir::HirId = id.into(); - if let Some(node) = map.find(hir_id) && let Some(body_id) = node.body_id() { - let body = map.body(body_id); - expr_finder.visit_expr(body.value); - let mut eraser = TypeEraser { tcx }; - let mut prev = eraser.fold_ty(ty); - let mut prev_span = None; + let Some(node) = map.find(hir_id) else { return false; }; + let Some(body_id) = node.body_id() else { return false; }; + let body = map.body(body_id); + expr_finder.visit_expr(body.value); + let mut eraser = TypeEraser { tcx }; + let mut prev = eraser.fold_ty(ty); + let mut prev_span = None; - for binding in expr_finder.uses { - // In every expression where the binding is referenced, we will look at that - // expression's type and see if it is where the incorrect found type was fully - // "materialized" and point at it. We will also try to provide a suggestion there. - let parent = map.get_parent_node(binding.hir_id); - if let Some(hir::Node::Expr(expr)) - | Some(hir::Node::Stmt(hir::Stmt { - kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr), - .. - })) = &map.find(parent) - && let hir::ExprKind::MethodCall(s, rcvr, args, _span) = expr.kind - && rcvr.hir_id == binding.hir_id - && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id) - { - // We special case methods, because they can influence inference through the - // call's arguments and we can provide a more explicit span. - let sig = self.tcx.fn_sig(def_id); - let def_self_ty = sig.input(0).skip_binder(); - let rcvr_ty = self.node_ty(rcvr.hir_id); - // Get the evaluated type *after* calling the method call, so that the influence - // of the arguments can be reflected in the receiver type. The receiver - // expression has the type *before* theis analysis is done. - let ty = match self.lookup_probe(s.ident, rcvr_ty, expr, probe::ProbeScope::TraitsInScope) { - Ok(pick) => pick.self_ty, - Err(_) => rcvr_ty, - }; - // Remove one layer of references to account for `&mut self` and - // `&self`, so that we can compare it against the binding. - let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) { - (ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty), - _ => (ty, def_self_ty), - }; - let mut param_args = FxHashMap::default(); - let mut param_expected = FxHashMap::default(); - let mut param_found = FxHashMap::default(); - if self.can_eq(self.param_env, ty, found).is_ok() { - // We only point at the first place where the found type was inferred. - for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() { - if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() { - // We found an argument that references a type parameter in `Self`, - // so we assume that this is the argument that caused the found - // type, which we know already because of `can_eq` above was first - // inferred in this method call. - let arg = &args[i]; - let arg_ty = self.node_ty(arg.hir_id); - err.span_label( - arg.span, - &format!( - "this is of type `{arg_ty}`, which makes `{ident}` to be \ - inferred as `{ty}`", - ), - ); - param_args.insert(param_ty, (arg, arg_ty)); - } + for binding in expr_finder.uses { + // In every expression where the binding is referenced, we will look at that + // expression's type and see if it is where the incorrect found type was fully + // "materialized" and point at it. We will also try to provide a suggestion there. + let parent = map.get_parent_node(binding.hir_id); + if let Some(hir::Node::Expr(expr)) + | Some(hir::Node::Stmt(hir::Stmt { + kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr), + .. + })) = &map.find(parent) + && let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind + && rcvr.hir_id == binding.hir_id + && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id) + { + // We special case methods, because they can influence inference through the + // call's arguments and we can provide a more explicit span. + let sig = self.tcx.fn_sig(def_id); + let def_self_ty = sig.input(0).skip_binder(); + let rcvr_ty = self.node_ty(rcvr.hir_id); + // Get the evaluated type *after* calling the method call, so that the influence + // of the arguments can be reflected in the receiver type. The receiver + // expression has the type *before* theis analysis is done. + let ty = match self.lookup_probe( + segment.ident, + rcvr_ty, + expr, + probe::ProbeScope::TraitsInScope, + ) { + Ok(pick) => pick.self_ty, + Err(_) => rcvr_ty, + }; + // Remove one layer of references to account for `&mut self` and + // `&self`, so that we can compare it against the binding. + let (ty, def_self_ty) = match (ty.kind(), def_self_ty.kind()) { + (ty::Ref(_, ty, a), ty::Ref(_, self_ty, b)) if a == b => (*ty, *self_ty), + _ => (ty, def_self_ty), + }; + let mut param_args = FxHashMap::default(); + let mut param_expected = FxHashMap::default(); + let mut param_found = FxHashMap::default(); + if self.can_eq(self.param_env, ty, found).is_ok() { + // We only point at the first place where the found type was inferred. + for (i, param_ty) in sig.inputs().skip_binder().iter().skip(1).enumerate() { + if def_self_ty.contains(*param_ty) && let ty::Param(_) = param_ty.kind() { + // We found an argument that references a type parameter in `Self`, + // so we assume that this is the argument that caused the found + // type, which we know already because of `can_eq` above was first + // inferred in this method call. + let arg = &args[i]; + let arg_ty = self.node_ty(arg.hir_id); + err.span_label( + arg.span, + &format!( + "this is of type `{arg_ty}`, which makes `{ident}` to be \ + inferred as `{ty}`", + ), + ); + param_args.insert(param_ty, (arg, arg_ty)); } } - - // Here we find, for a type param `T`, the type that `T` is in the current - // method call *and* in the original expected type. That way, we can see if we - // can give any structured suggestion for the function argument. - let mut c = CollectAllMismatches { - infcx: &self.infcx, - param_env: self.param_env, - errors: vec![], - }; - let _ = c.relate(def_self_ty, ty); - for error in c.errors { - if let TypeError::Sorts(error) = error { - param_found.insert(error.expected, error.found); - } - } - c.errors = vec![]; - let _ = c.relate(def_self_ty, expected); - for error in c.errors { - if let TypeError::Sorts(error) = error { - param_expected.insert(error.expected, error.found); - } - } - for (param, (arg,arg_ty)) in param_args.iter() { - let Some(expected) = param_expected.get(param) else { continue; }; - let Some(found) = param_found.get(param) else { continue; }; - if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; } - self.suggest_deref_ref_or_into(err, arg, *expected, *found, None); - } - - let ty = eraser.fold_ty(ty); - if ty.references_error() { - break; - } - if ty != prev - && param_args.is_empty() - && self.can_eq(self.param_env, ty, found).is_ok() - { - // We only point at the first place where the found type was inferred. - err.span_label( - s.ident.span, - with_forced_trimmed_paths!(format!( - "here the type of `{ident}` is inferred to be `{ty}`", - )), - ); - break; - } - prev = ty; - } else { - let ty = eraser.fold_ty(self.node_ty(binding.hir_id)); - if ty.references_error() { - break; - } - if ty != prev && let Some(span) = prev_span && self.can_eq(self.param_env, ty, found).is_ok() { - // We only point at the first place where the found type was inferred. - // We use the *previous* span because if the type is known *here* it means - // it was *evaluated earlier*. We don't do this for method calls because we - // evaluate the method's self type eagerly, but not in any other case. - err.span_label( - span, - with_forced_trimmed_paths!(format!( - "here the type of `{ident}` is inferred to be `{ty}`", - )), - ); - break; - } - prev = ty; } - if binding.hir_id == expr.hir_id { - // Do not look at expressions that come after the expression we were originally - // evaluating and had a type error. + + // Here we find, for a type param `T`, the type that `T` is in the current + // method call *and* in the original expected type. That way, we can see if we + // can give any structured suggestion for the function argument. + let mut c = CollectAllMismatches { + infcx: &self.infcx, + param_env: self.param_env, + errors: vec![], + }; + let _ = c.relate(def_self_ty, ty); + for error in c.errors { + if let TypeError::Sorts(error) = error { + param_found.insert(error.expected, error.found); + } + } + c.errors = vec![]; + let _ = c.relate(def_self_ty, expected); + for error in c.errors { + if let TypeError::Sorts(error) = error { + param_expected.insert(error.expected, error.found); + } + } + for (param, (arg,arg_ty)) in param_args.iter() { + let Some(expected) = param_expected.get(param) else { continue; }; + let Some(found) = param_found.get(param) else { continue; }; + if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; } + self.suggest_deref_ref_or_into(err, arg, *expected, *found, None); + } + + let ty = eraser.fold_ty(ty); + if ty.references_error() { break; } - prev_span = Some(binding.span); + if ty != prev + && param_args.is_empty() + && self.can_eq(self.param_env, ty, found).is_ok() + { + // We only point at the first place where the found type was inferred. + err.span_label( + segment.ident.span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + ); + break; + } + prev = ty; + } else { + let ty = eraser.fold_ty(self.node_ty(binding.hir_id)); + if ty.references_error() { + break; + } + if ty != prev + && let Some(span) = prev_span + && self.can_eq(self.param_env, ty, found).is_ok() + { + // We only point at the first place where the found type was inferred. + // We use the *previous* span because if the type is known *here* it means + // it was *evaluated earlier*. We don't do this for method calls because we + // evaluate the method's self type eagerly, but not in any other case. + err.span_label( + span, + with_forced_trimmed_paths!(format!( + "here the type of `{ident}` is inferred to be `{ty}`", + )), + ); + break; + } + prev = ty; } + if binding.hir_id == expr.hir_id { + // Do not look at expressions that come after the expression we were originally + // evaluating and had a type error. + break; + } + prev_span = Some(binding.span); } true } From ad82eedfa190b3cd39a535a6e858d79f69c89ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Jan 2023 20:49:47 -0800 Subject: [PATCH 157/223] Use `BottomUpFolder` --- compiler/rustc_hir_typeck/src/demand.rs | 57 ++++++------------- .../rustc_infer/src/infer/opaque_types.rs | 2 +- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 41bbe2d15c16..abff26375191 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -13,12 +13,10 @@ use rustc_middle::lint::in_external_macro; use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::fold::TypeFolder; +use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder}; use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; use rustc_middle::ty::relate::TypeRelation; -use rustc_middle::ty::{ - self, Article, AssocItem, Ty, TyCtxt, TypeAndMut, TypeSuperFoldable, TypeVisitable, -}; +use rustc_middle::ty::{self, Article, AssocItem, Ty, TypeAndMut, TypeVisitable}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{BytePos, Span}; use rustc_trait_selection::infer::InferCtxtExt as _; @@ -222,42 +220,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, expected: Ty<'tcx>, ) -> bool { - let tcx = self.tcx; let map = self.tcx.hir(); - // Hack to make equality checks on types with inference variables and regions useful. - struct TypeEraser<'tcx> { - tcx: TyCtxt<'tcx>, - } - impl<'tcx> TypeFolder<'tcx> for TypeEraser<'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { - self.tcx - } - fn fold_region(&mut self, _r: ty::Region<'tcx>) -> ty::Region<'tcx> { - self.tcx().lifetimes.re_erased - } - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_infer() && !t.has_erasable_regions() { - return t; - } - match *t.kind() { - ty::Infer(ty::TyVar(_) | ty::FreshTy(_)) => { - self.tcx.mk_ty_infer(ty::TyVar(ty::TyVid::from_u32(0))) - } - ty::Infer(ty::IntVar(_) | ty::FreshIntTy(_)) => { - self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 })) - } - ty::Infer(ty::FloatVar(_) | ty::FreshFloatTy(_)) => { - self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 })) - } - _ => t.super_fold_with(self), - } - } - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - ct.super_fold_with(self) - } - } - let hir::ExprKind::Path(hir::QPath::Resolved(None, p)) = expr.kind else { return false; }; let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; }; let hir::def::Res::Local(hir_id) = p.res else { return false; }; @@ -298,7 +262,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Some(body_id) = node.body_id() else { return false; }; let body = map.body(body_id); expr_finder.visit_expr(body.value); - let mut eraser = TypeEraser { tcx }; + // Hack to make equality checks on types with inference variables and regions useful. + let mut eraser = BottomUpFolder { + tcx: self.tcx, + lt_op: |_| self.tcx.lifetimes.re_erased, + ct_op: |c| c, + ty_op: |t| match *t.kind() { + ty::Infer(ty::TyVar(vid)) => self.tcx.mk_ty_infer(ty::TyVar(self.root_var(vid))), + ty::Infer(ty::IntVar(_)) => { + self.tcx.mk_ty_infer(ty::IntVar(ty::IntVid { index: 0 })) + } + ty::Infer(ty::FloatVar(_)) => { + self.tcx.mk_ty_infer(ty::FloatVar(ty::FloatVid { index: 0 })) + } + _ => t, + }, + }; let mut prev = eraser.fold_ty(ty); let mut prev_span = None; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index a130fde47ed5..749e960bfd03 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> { .as_local() .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some()) }; - let value = value.fold_with(&mut ty::fold::BottomUpFolder { + let value = value.fold_with(&mut BottomUpFolder { tcx: self.tcx, lt_op: |lt| lt, ct_op: |ct| ct, From c905f5e1b0315f9637b2f7e52c807e46b2e24ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 00:18:57 +0000 Subject: [PATCH 158/223] Account for type error on method arg caused by earlier inference ```rust fn main() { let v = Vec::new(); v.push(0); v.push(0); v.push(""); } ``` now produces ``` error[E0308]: mismatched types --> $DIR/point-at-inference-3.rs:6:12 | LL | v.push(0); | - this is of type `{integer}`, which makes `v` to be inferred as `Vec<{integer}>` ... LL | v.push(""); | ---- ^^ expected integer, found `&str` | | | arguments to this function are incorrect | note: associated function defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ``` --- compiler/rustc_hir_typeck/src/demand.rs | 4 +++- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 12 ++++++++++++ .../ui/type/type-check/point-at-inference-3.rs | 10 ++++++++++ .../type/type-check/point-at-inference-3.stderr | 17 +++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/type/type-check/point-at-inference-3.rs create mode 100644 src/test/ui/type/type-check/point-at-inference-3.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index abff26375191..cff74cd9693d 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -213,7 +213,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (expected, Some(err)) } - fn point_at_expr_source_of_inferred_type( + pub fn point_at_expr_source_of_inferred_type( &self, err: &mut Diagnostic, expr: &hir::Expr<'_>, @@ -387,6 +387,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )), ); break; + } else if !param_args.is_empty() { + break; } prev = ty; } else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 55280487adda..7d6b4aaebf4e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -798,6 +798,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { full_call_span, format!("arguments to this {} are incorrect", call_name), ); + if let (Some(callee_ty), hir::ExprKind::MethodCall(_, rcvr, _, _)) = + (callee_ty, &call_expr.kind) + { + // Type that would have accepted this argument if it hadn't been inferred earlier. + // FIXME: We leave an inference variable for now, but it'd be nice to get a more + // specific type to increase the accuracy of the diagnostic. + let expected = self.infcx.next_ty_var(TypeVariableOrigin { + kind: TypeVariableOriginKind::MiscVariable, + span: full_call_span, + }); + self.point_at_expr_source_of_inferred_type(&mut err, rcvr, expected, callee_ty); + } // Call out where the function is defined self.label_fn_like( &mut err, diff --git a/src/test/ui/type/type-check/point-at-inference-3.rs b/src/test/ui/type/type-check/point-at-inference-3.rs new file mode 100644 index 000000000000..893306d41054 --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference-3.rs @@ -0,0 +1,10 @@ +fn main() { + let v = Vec::new(); + v.push(0); + //~^ NOTE this is of type `{integer}`, which makes `v` to be inferred as `Vec<{integer}>` + v.push(0); + v.push(""); //~ ERROR mismatched types + //~^ NOTE expected integer, found `&str` + //~| NOTE arguments to this function are incorrect + //~| NOTE associated function defined here +} diff --git a/src/test/ui/type/type-check/point-at-inference-3.stderr b/src/test/ui/type/type-check/point-at-inference-3.stderr new file mode 100644 index 000000000000..01264edf6b6e --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference-3.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/point-at-inference-3.rs:6:12 + | +LL | v.push(0); + | - this is of type `{integer}`, which makes `v` to be inferred as `Vec<{integer}>` +... +LL | v.push(""); + | ---- ^^ expected integer, found `&str` + | | + | arguments to this function are incorrect + | +note: associated function defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From f571862d174e3d26002bf52138ead476bf068f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 00:37:53 +0000 Subject: [PATCH 159/223] Suggest changing argument on type error --- .../ui/type/type-check/point-at-inference-3.fixed | 12 ++++++++++++ .../ui/type/type-check/point-at-inference-3.rs | 12 +++++++----- .../ui/type/type-check/point-at-inference-3.stderr | 14 +++++++++----- 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/type/type-check/point-at-inference-3.fixed diff --git a/src/test/ui/type/type-check/point-at-inference-3.fixed b/src/test/ui/type/type-check/point-at-inference-3.fixed new file mode 100644 index 000000000000..ff299940a576 --- /dev/null +++ b/src/test/ui/type/type-check/point-at-inference-3.fixed @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + let mut v = Vec::new(); + v.push(0i32); + //~^ NOTE this is of type `i32`, which makes `v` to be inferred as `Vec` + v.push(0); + v.push(1i32); //~ ERROR mismatched types + //~^ NOTE expected `i32`, found `u32` + //~| NOTE arguments to this function are incorrect + //~| NOTE associated function defined here + //~| HELP change the type of the numeric literal from `u32` to `i32` +} diff --git a/src/test/ui/type/type-check/point-at-inference-3.rs b/src/test/ui/type/type-check/point-at-inference-3.rs index 893306d41054..812a39e4aaf3 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.rs +++ b/src/test/ui/type/type-check/point-at-inference-3.rs @@ -1,10 +1,12 @@ +// run-rustfix fn main() { - let v = Vec::new(); + let mut v = Vec::new(); + v.push(0i32); + //~^ NOTE this is of type `i32`, which makes `v` to be inferred as `Vec` v.push(0); - //~^ NOTE this is of type `{integer}`, which makes `v` to be inferred as `Vec<{integer}>` - v.push(0); - v.push(""); //~ ERROR mismatched types - //~^ NOTE expected integer, found `&str` + v.push(1u32); //~ ERROR mismatched types + //~^ NOTE expected `i32`, found `u32` //~| NOTE arguments to this function are incorrect //~| NOTE associated function defined here + //~| HELP change the type of the numeric literal from `u32` to `i32` } diff --git a/src/test/ui/type/type-check/point-at-inference-3.stderr b/src/test/ui/type/type-check/point-at-inference-3.stderr index 01264edf6b6e..4e7779694669 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.stderr +++ b/src/test/ui/type/type-check/point-at-inference-3.stderr @@ -1,16 +1,20 @@ error[E0308]: mismatched types - --> $DIR/point-at-inference-3.rs:6:12 + --> $DIR/point-at-inference-3.rs:7:12 | -LL | v.push(0); - | - this is of type `{integer}`, which makes `v` to be inferred as `Vec<{integer}>` +LL | v.push(0i32); + | ---- this is of type `i32`, which makes `v` to be inferred as `Vec` ... -LL | v.push(""); - | ---- ^^ expected integer, found `&str` +LL | v.push(1u32); + | ---- ^^^^ expected `i32`, found `u32` | | | arguments to this function are incorrect | note: associated function defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL +help: change the type of the numeric literal from `u32` to `i32` + | +LL | v.push(1i32); + | ~~~ error: aborting due to previous error From 98f3936aa7e99f54ff377a77f9b03cea2c2c29d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 01:00:21 +0000 Subject: [PATCH 160/223] review comment: potentially produce more suggestions for arg type mismatch --- compiler/rustc_hir_typeck/src/demand.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index cff74cd9693d..06f34abbea26 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -364,11 +364,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param_expected.insert(error.expected, error.found); } } - for (param, (arg,arg_ty)) in param_args.iter() { + for (param, (arg, arg_ty)) in param_args.iter() { let Some(expected) = param_expected.get(param) else { continue; }; let Some(found) = param_found.get(param) else { continue; }; if self.can_eq(self.param_env, *arg_ty, *found).is_err() { continue; } - self.suggest_deref_ref_or_into(err, arg, *expected, *found, None); + self.emit_coerce_suggestions(err, arg, *found, *expected, None, None); } let ty = eraser.fold_ty(ty); From b182259d391a033a3a7017a7be7d5494405fc8e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 01:26:44 +0000 Subject: [PATCH 161/223] review comments: reword --- compiler/rustc_hir_typeck/src/demand.rs | 2 +- src/test/ui/type/type-check/point-at-inference-3.fixed | 2 +- src/test/ui/type/type-check/point-at-inference-3.rs | 2 +- src/test/ui/type/type-check/point-at-inference-3.stderr | 2 +- src/test/ui/type/type-check/point-at-inference.stderr | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 06f34abbea26..6cf515cbb0ad 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -334,7 +334,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( arg.span, &format!( - "this is of type `{arg_ty}`, which makes `{ident}` to be \ + "this is of type `{arg_ty}`, which causes `{ident}` to be \ inferred as `{ty}`", ), ); diff --git a/src/test/ui/type/type-check/point-at-inference-3.fixed b/src/test/ui/type/type-check/point-at-inference-3.fixed index ff299940a576..870f2779b8c4 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.fixed +++ b/src/test/ui/type/type-check/point-at-inference-3.fixed @@ -2,7 +2,7 @@ fn main() { let mut v = Vec::new(); v.push(0i32); - //~^ NOTE this is of type `i32`, which makes `v` to be inferred as `Vec` + //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec` v.push(0); v.push(1i32); //~ ERROR mismatched types //~^ NOTE expected `i32`, found `u32` diff --git a/src/test/ui/type/type-check/point-at-inference-3.rs b/src/test/ui/type/type-check/point-at-inference-3.rs index 812a39e4aaf3..a4471e12fc2a 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.rs +++ b/src/test/ui/type/type-check/point-at-inference-3.rs @@ -2,7 +2,7 @@ fn main() { let mut v = Vec::new(); v.push(0i32); - //~^ NOTE this is of type `i32`, which makes `v` to be inferred as `Vec` + //~^ NOTE this is of type `i32`, which causes `v` to be inferred as `Vec` v.push(0); v.push(1u32); //~ ERROR mismatched types //~^ NOTE expected `i32`, found `u32` diff --git a/src/test/ui/type/type-check/point-at-inference-3.stderr b/src/test/ui/type/type-check/point-at-inference-3.stderr index 4e7779694669..c373c6722fdd 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.stderr +++ b/src/test/ui/type/type-check/point-at-inference-3.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/point-at-inference-3.rs:7:12 | LL | v.push(0i32); - | ---- this is of type `i32`, which makes `v` to be inferred as `Vec` + | ---- this is of type `i32`, which causes `v` to be inferred as `Vec` ... LL | v.push(1u32); | ---- ^^^^ expected `i32`, found `u32` diff --git a/src/test/ui/type/type-check/point-at-inference.stderr b/src/test/ui/type/type-check/point-at-inference.stderr index 197511bf64ef..70428fe841b9 100644 --- a/src/test/ui/type/type-check/point-at-inference.stderr +++ b/src/test/ui/type/type-check/point-at-inference.stderr @@ -2,7 +2,7 @@ error[E0308]: mismatched types --> $DIR/point-at-inference.rs:12:9 | LL | foo.push(i); - | - this is of type `&{integer}`, which makes `foo` to be inferred as `Vec<&{integer}>` + | - this is of type `&{integer}`, which causes `foo` to be inferred as `Vec<&{integer}>` ... LL | bar(foo); | --- ^^^ expected `i32`, found `&{integer}` From 23c3a307300827dbd53637742905293b9240506a Mon Sep 17 00:00:00 2001 From: clubby789 Date: Tue, 3 Jan 2023 17:02:25 +0000 Subject: [PATCH 162/223] Explain error with `&mut self` for unsized trait impls --- .../src/diagnostics/mutability_errors.rs | 27 +++++++++++-------- src/test/ui/borrowck/issue-93078.rs | 15 +++++++++++ src/test/ui/borrowck/issue-93078.stderr | 12 +++++++++ 3 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/borrowck/issue-93078.rs create mode 100644 src/test/ui/borrowck/issue-93078.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 6f6d1b01bd42..bf830e276999 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -344,20 +344,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { err.span_help(source_info.span, "try removing `&mut` here"); } - } else if decl.mutability == Mutability::Not - && !matches!( + } else if decl.mutability == Mutability::Not { + if matches!( decl.local_info, Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf( hir::ImplicitSelfKind::MutRef - )))) - ) - { - err.span_suggestion_verbose( - decl.source_info.span.shrink_to_lo(), - "consider making the binding mutable", - "mut ", - Applicability::MachineApplicable, - ); + ),))) + ) { + err.note( + "as `Self` may be unsized, this call attempts to take `&mut &mut self`", + ); + err.note("however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably"); + } else { + err.span_suggestion_verbose( + decl.source_info.span.shrink_to_lo(), + "consider making the binding mutable", + "mut ", + Applicability::MachineApplicable, + ); + }; } } diff --git a/src/test/ui/borrowck/issue-93078.rs b/src/test/ui/borrowck/issue-93078.rs new file mode 100644 index 000000000000..2e608c5db3e1 --- /dev/null +++ b/src/test/ui/borrowck/issue-93078.rs @@ -0,0 +1,15 @@ +trait Modify { + fn modify(&mut self) ; +} + +impl Modify for T { + fn modify(&mut self) {} +} + +trait Foo { + fn mute(&mut self) { + self.modify(); //~ ERROR cannot borrow `self` as mutable + } +} + +fn main() {} diff --git a/src/test/ui/borrowck/issue-93078.stderr b/src/test/ui/borrowck/issue-93078.stderr new file mode 100644 index 000000000000..771a652a1739 --- /dev/null +++ b/src/test/ui/borrowck/issue-93078.stderr @@ -0,0 +1,12 @@ +error[E0596]: cannot borrow `self` as mutable, as it is not declared as mutable + --> $DIR/issue-93078.rs:11:9 + | +LL | self.modify(); + | ^^^^^^^^^^^^^ cannot borrow as mutable + | + = note: as `Self` may be unsized, this call attempts to take `&mut &mut self` + = note: however, `&mut self` expands to `self: &mut Self`, therefore `self` cannot be borrowed mutably + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0596`. From f98f2fcb5e4985bd7b12bae4ec03f2d96197fb2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 17:06:34 +0000 Subject: [PATCH 163/223] fix rebase --- compiler/rustc_hir_typeck/src/demand.rs | 10 ++++------ src/test/ui/type/type-check/point-at-inference-3.fixed | 2 +- src/test/ui/type/type-check/point-at-inference-3.rs | 2 +- .../ui/type/type-check/point-at-inference-3.stderr | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 6cf515cbb0ad..cf070eb962f0 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -226,12 +226,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let [hir::PathSegment { ident, args: None, .. }] = p.segments else { return false; }; let hir::def::Res::Local(hir_id) = p.res else { return false; }; let Some(hir::Node::Pat(pat)) = map.find(hir_id) else { return false; }; - let parent = map.get_parent_node(pat.hir_id); let Some(hir::Node::Local(hir::Local { ty: None, init: Some(init), .. - })) = map.find(parent) else { return false; }; + })) = map.find_parent(pat.hir_id) else { return false; }; let Some(ty) = self.node_ty_opt(init.hir_id) else { return false; }; if ty.is_closure() || init.span.overlaps(expr.span) || pat.span.from_expansion() { return false; @@ -285,12 +284,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // In every expression where the binding is referenced, we will look at that // expression's type and see if it is where the incorrect found type was fully // "materialized" and point at it. We will also try to provide a suggestion there. - let parent = map.get_parent_node(binding.hir_id); - if let Some(hir::Node::Expr(expr)) - | Some(hir::Node::Stmt(hir::Stmt { + if let Some(hir::Node::Expr(expr) + | hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr), .. - })) = &map.find(parent) + })) = &map.find_parent(binding.hir_id) && let hir::ExprKind::MethodCall(segment, rcvr, args, _span) = expr.kind && rcvr.hir_id == binding.hir_id && let Some(def_id) = self.typeck_results.borrow().type_dependent_def_id(expr.hir_id) diff --git a/src/test/ui/type/type-check/point-at-inference-3.fixed b/src/test/ui/type/type-check/point-at-inference-3.fixed index 870f2779b8c4..1a960133ceba 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.fixed +++ b/src/test/ui/type/type-check/point-at-inference-3.fixed @@ -6,7 +6,7 @@ fn main() { v.push(0); v.push(1i32); //~ ERROR mismatched types //~^ NOTE expected `i32`, found `u32` - //~| NOTE arguments to this function are incorrect + //~| NOTE arguments to this method are incorrect //~| NOTE associated function defined here //~| HELP change the type of the numeric literal from `u32` to `i32` } diff --git a/src/test/ui/type/type-check/point-at-inference-3.rs b/src/test/ui/type/type-check/point-at-inference-3.rs index a4471e12fc2a..92910ae1a311 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.rs +++ b/src/test/ui/type/type-check/point-at-inference-3.rs @@ -6,7 +6,7 @@ fn main() { v.push(0); v.push(1u32); //~ ERROR mismatched types //~^ NOTE expected `i32`, found `u32` - //~| NOTE arguments to this function are incorrect + //~| NOTE arguments to this method are incorrect //~| NOTE associated function defined here //~| HELP change the type of the numeric literal from `u32` to `i32` } diff --git a/src/test/ui/type/type-check/point-at-inference-3.stderr b/src/test/ui/type/type-check/point-at-inference-3.stderr index c373c6722fdd..999c3148362f 100644 --- a/src/test/ui/type/type-check/point-at-inference-3.stderr +++ b/src/test/ui/type/type-check/point-at-inference-3.stderr @@ -7,7 +7,7 @@ LL | v.push(0i32); LL | v.push(1u32); | ---- ^^^^ expected `i32`, found `u32` | | - | arguments to this function are incorrect + | arguments to this method are incorrect | note: associated function defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL From de1859fc324a323dfd0033d666c64f82ff2f130f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 5 Jan 2023 17:57:55 +0000 Subject: [PATCH 164/223] Correct detection of elided lifetimes in impl-trait. --- compiler/rustc_hir_analysis/src/collect/lifetimes.rs | 6 ++++-- .../ui/suggestions/impl-trait-missing-lifetime-gated.rs | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs index 0a1188c16a8b..35f10dc87374 100644 --- a/compiler/rustc_hir_analysis/src/collect/lifetimes.rs +++ b/compiler/rustc_hir_analysis/src/collect/lifetimes.rs @@ -1195,8 +1195,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // Fresh lifetimes in APIT used to be allowed in async fns and forbidden in // regular fns. if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin - && let hir::LifetimeName::Param(_) = lifetime_ref.res - && lifetime_ref.is_anonymous() + && let hir::LifetimeName::Param(param_id) = lifetime_ref.res + && let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id)) + && let Some(param) = generics.params.iter().find(|p| p.def_id == param_id) + && param.is_elided_lifetime() && let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id) && !self.tcx.features().anonymous_lifetime_in_impl_trait { diff --git a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs index 9839e973bdfe..a1a51c4814e8 100644 --- a/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs +++ b/src/test/ui/suggestions/impl-trait-missing-lifetime-gated.rs @@ -60,4 +60,9 @@ mod in_path { //~| ERROR missing lifetime specifier } +// This must not err, as the `&` actually resolves to `'a`. +fn resolved_anonymous<'a, T>(f: impl Fn(&'a str) -> &T) { + f("f") +} + fn main() {} From fd7a15971069156f1741fb3a3c34c9f0c54d5744 Mon Sep 17 00:00:00 2001 From: nils <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 19 Dec 2022 10:31:55 +0100 Subject: [PATCH 165/223] Fix `uninlined_format_args` for some compiler crates Convert all the crates that have had their diagnostic migration completed (except save_analysis because that will be deleted soon and apfloat because of the licensing problem). --- compiler/rustc_ast/src/ast.rs | 6 +-- compiler/rustc_ast/src/ast_traits.rs | 4 +- compiler/rustc_ast/src/attr/mod.rs | 2 +- compiler/rustc_ast/src/expand/allocator.rs | 4 +- compiler/rustc_ast/src/token.rs | 14 +++---- compiler/rustc_ast/src/tokenstream.rs | 3 +- compiler/rustc_ast/src/util/literal.rs | 6 +-- compiler/rustc_ast_lowering/src/asm.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 8 ++-- compiler/rustc_ast_pretty/src/pprust/state.rs | 16 ++++---- .../rustc_ast_pretty/src/pprust/state/item.rs | 4 +- compiler/rustc_attr/src/builtin.rs | 4 +- .../rustc_attr/src/session_diagnostics.rs | 2 +- .../src/graph/dominators/mod.rs | 4 +- .../src/graph/scc/mod.rs | 14 +++---- .../src/obligation_forest/graphviz.rs | 4 +- .../rustc_data_structures/src/profiling.rs | 2 +- .../rustc_data_structures/src/small_c_str.rs | 6 +-- compiler/rustc_data_structures/src/vec_map.rs | 3 +- compiler/rustc_driver/src/args.rs | 6 +-- compiler/rustc_driver/src/lib.rs | 41 +++++++++---------- compiler/rustc_driver/src/pretty.rs | 6 +-- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- compiler/rustc_feature/src/lib.rs | 2 +- compiler/rustc_graphviz/src/lib.rs | 12 +++--- compiler/rustc_hir/src/def.rs | 3 +- compiler/rustc_hir/src/definitions.rs | 11 +++-- compiler/rustc_hir/src/hir_id.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 8 ++-- compiler/rustc_index/src/bit_set.rs | 2 +- compiler/rustc_index/src/interval.rs | 5 +-- compiler/rustc_interface/src/interface.rs | 6 +-- compiler/rustc_interface/src/passes.rs | 6 +-- compiler/rustc_interface/src/util.rs | 13 +++--- compiler/rustc_llvm/build.rs | 28 ++++++------- compiler/rustc_log/src/lib.rs | 3 +- .../rustc_macros/src/diagnostics/error.rs | 16 ++++---- .../rustc_macros/src/diagnostics/fluent.rs | 4 +- .../src/diagnostics/subdiagnostic.rs | 3 +- .../rustc_macros/src/diagnostics/utils.rs | 8 ++-- compiler/rustc_macros/src/newtype.rs | 4 +- compiler/rustc_macros/src/query.rs | 2 +- compiler/rustc_macros/src/symbols.rs | 6 +-- compiler/rustc_metadata/src/creader.rs | 4 +- compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 +-- .../src/rmeta/decoder/cstore_impl.rs | 2 +- .../src/rmeta/def_path_hash_map.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 18 +++----- .../rustc_mir_dataflow/src/framework/fmt.rs | 4 +- .../src/framework/graphviz.rs | 18 ++++---- .../rustc_mir_dataflow/src/move_paths/mod.rs | 6 +-- .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- compiler/rustc_monomorphize/src/collector.rs | 2 +- compiler/rustc_monomorphize/src/errors.rs | 2 +- .../src/partitioning/mod.rs | 11 +++-- compiler/rustc_monomorphize/src/util.rs | 8 ++-- compiler/rustc_parse_format/src/lib.rs | 8 ++-- compiler/rustc_privacy/src/lib.rs | 2 +- .../rustc_query_impl/src/on_disk_cache.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 2 +- .../rustc_query_impl/src/profiling_support.rs | 2 +- .../rustc_query_system/src/dep_graph/debug.rs | 4 +- .../src/dep_graph/dep_node.rs | 2 +- .../rustc_query_system/src/dep_graph/graph.rs | 22 ++++------ .../src/dep_graph/serialized.rs | 13 +++--- .../rustc_query_system/src/query/plumbing.rs | 12 +++--- compiler/rustc_span/src/def_id.rs | 2 +- compiler/rustc_span/src/edition.rs | 2 +- compiler/rustc_span/src/hygiene.rs | 16 +++----- compiler/rustc_span/src/lib.rs | 4 +- compiler/rustc_span/src/profiling.rs | 2 +- compiler/rustc_symbol_mangling/src/legacy.rs | 4 +- compiler/rustc_symbol_mangling/src/lib.rs | 3 +- compiler/rustc_symbol_mangling/src/test.rs | 2 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 4 +- compiler/rustc_symbol_mangling/src/v0.rs | 4 +- compiler/rustc_target/src/abi/call/mod.rs | 8 ++-- compiler/rustc_target/src/asm/aarch64.rs | 2 +- compiler/rustc_target/src/asm/arm.rs | 2 +- compiler/rustc_target/src/asm/mod.rs | 14 +++---- compiler/rustc_target/src/asm/x86.rs | 30 +++++++------- compiler/rustc_target/src/spec/apple_base.rs | 10 ++--- compiler/rustc_target/src/spec/mod.rs | 12 +++--- compiler/rustc_target/src/spec/solid_base.rs | 2 +- compiler/rustc_traits/src/dropck_outlives.rs | 4 +- .../src/normalize_erasing_regions.rs | 2 +- compiler/rustc_transmute/src/layout/mod.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 12 +++--- compiler/rustc_type_ir/src/sty.rs | 6 +-- 91 files changed, 287 insertions(+), 329 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index c1b26ca09253..e656fb3740bb 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2170,10 +2170,10 @@ impl fmt::Display for InlineAsmTemplatePiece { Ok(()) } Self::Placeholder { operand_idx, modifier: Some(modifier), .. } => { - write!(f, "{{{}:{}}}", operand_idx, modifier) + write!(f, "{{{operand_idx}:{modifier}}}") } Self::Placeholder { operand_idx, modifier: None, .. } => { - write!(f, "{{{}}}", operand_idx) + write!(f, "{{{operand_idx}}}") } } } @@ -2185,7 +2185,7 @@ impl InlineAsmTemplatePiece { use fmt::Write; let mut out = String::new(); for p in s.iter() { - let _ = write!(out, "{}", p); + let _ = write!(out, "{p}"); } out } diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 1b31be07f7ad..4dc9c30a2c80 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -214,7 +214,7 @@ impl HasTokens for Attribute { match &self.kind { AttrKind::Normal(normal) => normal.tokens.as_ref(), kind @ AttrKind::DocComment(..) => { - panic!("Called tokens on doc comment attr {:?}", kind) + panic!("Called tokens on doc comment attr {kind:?}") } } } @@ -222,7 +222,7 @@ impl HasTokens for Attribute { Some(match &mut self.kind { AttrKind::Normal(normal) => &mut normal.tokens, kind @ AttrKind::DocComment(..) => { - panic!("Called tokens_mut on doc comment attr {:?}", kind) + panic!("Called tokens_mut on doc comment attr {kind:?}") } }) } diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs index d99f6ed2c1cd..c6b6207b3186 100644 --- a/compiler/rustc_ast/src/attr/mod.rs +++ b/compiler/rustc_ast/src/attr/mod.rs @@ -310,7 +310,7 @@ impl Attribute { AttrKind::Normal(normal) => normal .tokens .as_ref() - .unwrap_or_else(|| panic!("attribute is missing tokens: {:?}", self)) + .unwrap_or_else(|| panic!("attribute is missing tokens: {self:?}")) .to_attr_token_stream() .to_tokenstream(), &AttrKind::DocComment(comment_kind, data) => TokenStream::new(vec![TokenTree::Token( diff --git a/compiler/rustc_ast/src/expand/allocator.rs b/compiler/rustc_ast/src/expand/allocator.rs index 1976e4ad3c9f..359394963489 100644 --- a/compiler/rustc_ast/src/expand/allocator.rs +++ b/compiler/rustc_ast/src/expand/allocator.rs @@ -9,8 +9,8 @@ pub enum AllocatorKind { impl AllocatorKind { pub fn fn_name(&self, base: Symbol) -> String { match *self { - AllocatorKind::Global => format!("__rg_{}", base), - AllocatorKind::Default => format!("__rdl_{}", base), + AllocatorKind::Global => format!("__rg_{base}"), + AllocatorKind::Default => format!("__rdl_{base}"), } } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 5b6cf30fa96e..f947ae4d0573 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -125,27 +125,27 @@ impl fmt::Display for Lit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Lit { kind, symbol, suffix } = *self; match kind { - Byte => write!(f, "b'{}'", symbol)?, - Char => write!(f, "'{}'", symbol)?, - Str => write!(f, "\"{}\"", symbol)?, + Byte => write!(f, "b'{symbol}'")?, + Char => write!(f, "'{symbol}'")?, + Str => write!(f, "\"{symbol}\"")?, StrRaw(n) => write!( f, "r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol )?, - ByteStr => write!(f, "b\"{}\"", symbol)?, + ByteStr => write!(f, "b\"{symbol}\"")?, ByteStrRaw(n) => write!( f, "br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol )?, - Integer | Float | Bool | Err => write!(f, "{}", symbol)?, + Integer | Float | Bool | Err => write!(f, "{symbol}")?, } if let Some(suffix) = suffix { - write!(f, "{}", suffix)?; + write!(f, "{suffix}")?; } Ok(()) @@ -756,7 +756,7 @@ impl Token { _ => return None, }, SingleQuote => match joint.kind { - Ident(name, false) => Lifetime(Symbol::intern(&format!("'{}", name))), + Ident(name, false) => Lifetime(Symbol::intern(&format!("'{name}"))), _ => return None, }, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 29a5eb4b7c50..fabd43a1618a 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -258,8 +258,7 @@ impl AttrTokenStream { assert!( found, - "Failed to find trailing delimited group in: {:?}", - target_tokens + "Failed to find trailing delimited group in: {target_tokens:?}" ); } let mut flat: SmallVec<[_; 1]> = SmallVec::new(); diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index 69a9a5830483..74b842ac96ea 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -168,7 +168,7 @@ impl fmt::Display for LitKind { match *self { LitKind::Byte(b) => { let b: String = ascii::escape_default(b).map(Into::::into).collect(); - write!(f, "b'{}'", b)?; + write!(f, "b'{b}'")?; } LitKind::Char(ch) => write!(f, "'{}'", escape_char_symbol(ch))?, LitKind::Str(sym, StrStyle::Cooked) => write!(f, "\"{}\"", escape_string_symbol(sym))?, @@ -192,7 +192,7 @@ impl fmt::Display for LitKind { )?; } LitKind::Int(n, ty) => { - write!(f, "{}", n)?; + write!(f, "{n}")?; match ty { ast::LitIntType::Unsigned(ty) => write!(f, "{}", ty.name())?, ast::LitIntType::Signed(ty) => write!(f, "{}", ty.name())?, @@ -200,7 +200,7 @@ impl fmt::Display for LitKind { } } LitKind::Float(symbol, ty) => { - write!(f, "{}", symbol)?; + write!(f, "{symbol}")?; match ty { ast::LitFloatType::Suffixed(ty) => write!(f, "{}", ty.name())?, ast::LitFloatType::Unsuffixed => {} diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index dfef6ec70fcf..941d3179587e 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -104,7 +104,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { Err(supported_abis) => { let mut abis = format!("`{}`", supported_abis[0]); for m in &supported_abis[1..] { - let _ = write!(abis, ", `{}`", m); + let _ = write!(abis, ", `{m}`"); } self.tcx.sess.emit_err(InvalidAbiClobberAbi { abi_span: *abi_span, @@ -262,7 +262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let sub = if !valid_modifiers.is_empty() { let mut mods = format!("`{}`", valid_modifiers[0]); for m in &valid_modifiers[1..] { - let _ = write!(mods, ", `{}`", m); + let _ = write!(mods, ", `{m}`"); } InvalidAsmTemplateModifierRegClassSub::SupportModifier { class_name: class.name(), diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b6b242bfc27f..ea30bed5ace4 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1051,7 +1051,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } _ => { // Replace the ident for bindings that aren't simple. - let name = format!("__arg{}", index); + let name = format!("__arg{index}"); let ident = Ident::from_str(&name); (ident, false) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 83174afdb12e..2e135aafb1e0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -296,7 +296,7 @@ impl std::fmt::Display for ImplTraitPosition { ImplTraitPosition::ImplReturn => "`impl` method return", }; - write!(f, "{}", name) + write!(f, "{name}") } } @@ -503,7 +503,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn orig_local_def_id(&self, node: NodeId) -> LocalDefId { self.orig_opt_local_def_id(node) - .unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + .unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } /// Given the id of some node in the AST, finds the `LocalDefId` associated with it by the name @@ -524,7 +524,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } fn local_def_id(&self, node: NodeId) -> LocalDefId { - self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{:?}`", node)) + self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } /// Get the previously recorded `to` local def id given the `from` local def id, obtained using @@ -2197,7 +2197,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_ref(&mut self, p: &TraitRef, itctx: &ImplTraitContext) -> hir::TraitRef<'hir> { let path = match self.lower_qpath(p.ref_id, &None, &p.path, ParamMode::Explicit, itctx) { hir::QPath::Resolved(None, path) => path, - qpath => panic!("lower_trait_ref: unexpected QPath `{:?}`", qpath), + qpath => panic!("lower_trait_ref: unexpected QPath `{qpath:?}`"), }; hir::TraitRef { path, hir_ref_id: self.lower_node_id(p.ref_id) } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 104cdd3a8e11..6a8064b0e874 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -191,23 +191,23 @@ fn doc_comment_to_string( data: Symbol, ) -> String { match (comment_kind, attr_style) { - (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{}", data), - (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{}", data), - (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{}*/", data), - (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{}*/", data), + (CommentKind::Line, ast::AttrStyle::Outer) => format!("///{data}"), + (CommentKind::Line, ast::AttrStyle::Inner) => format!("//!{data}"), + (CommentKind::Block, ast::AttrStyle::Outer) => format!("/**{data}*/"), + (CommentKind::Block, ast::AttrStyle::Inner) => format!("/*!{data}*/"), } } pub fn literal_to_string(lit: token::Lit) -> String { let token::Lit { kind, symbol, suffix } = lit; let mut out = match kind { - token::Byte => format!("b'{}'", symbol), - token::Char => format!("'{}'", symbol), - token::Str => format!("\"{}\"", symbol), + token::Byte => format!("b'{symbol}'"), + token::Char => format!("'{symbol}'"), + token::Str => format!("\"{symbol}\""), token::StrRaw(n) => { format!("r{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) } - token::ByteStr => format!("b\"{}\"", symbol), + token::ByteStr => format!("b\"{symbol}\""), token::ByteStrRaw(n) => { format!("br{delim}\"{string}\"{delim}", delim = "#".repeat(n as usize), string = symbol) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 5b6a07721e2b..bf2c73a66a2c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -411,9 +411,9 @@ impl<'a> State<'a> { ast::VisibilityKind::Restricted { path, shorthand, .. } => { let path = Self::to_string(|s| s.print_path(path, false, 0)); if *shorthand && (path == "crate" || path == "self" || path == "super") { - self.word_nbsp(format!("pub({})", path)) + self.word_nbsp(format!("pub({path})")) } else { - self.word_nbsp(format!("pub(in {})", path)) + self.word_nbsp(format!("pub(in {path})")) } } ast::VisibilityKind::Inherited => {} diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index ab5e19050ead..40531c1c164f 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -619,7 +619,7 @@ fn try_gate_cfg(name: Symbol, span: Span, sess: &ParseSess, features: Option<&Fe fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &Features) { let (cfg, feature, has_feature) = gated_cfg; if !has_feature(features) && !cfg_span.allows_unstable(*feature) { - let explain = format!("`cfg({})` is experimental and subject to change", cfg); + let explain = format!("`cfg({cfg})` is experimental and subject to change"); feature_err(sess, *feature, cfg_span, &explain).emit(); } } @@ -975,7 +975,7 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec { } pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec { - assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {:?}", attr); + assert!(attr.has_name(sym::repr), "expected `#[repr(..)]`, found: {attr:?}"); use ReprAttr::*; let mut acc = Vec::new(); let diagnostic = &sess.parse_sess.span_diagnostic; diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 91c6bcb08a07..3ba7a3c5336b 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -51,7 +51,7 @@ pub(crate) struct UnknownMetaItem<'a> { // Manual implementation to be able to format `expected` items correctly. impl<'a> IntoDiagnostic<'a> for UnknownMetaItem<'_> { fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, ErrorGuaranteed> { - let expected = self.expected.iter().map(|name| format!("`{}`", name)).collect::>(); + let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::>(); let mut diag = handler.struct_span_err_with_code( self.span, fluent::attr_unknown_meta_item, diff --git a/compiler/rustc_data_structures/src/graph/dominators/mod.rs b/compiler/rustc_data_structures/src/graph/dominators/mod.rs index 94a8c1fc051d..ea2a4388b92f 100644 --- a/compiler/rustc_data_structures/src/graph/dominators/mod.rs +++ b/compiler/rustc_data_structures/src/graph/dominators/mod.rs @@ -277,12 +277,12 @@ impl Dominators { } pub fn immediate_dominator(&self, node: Node) -> Node { - assert!(self.is_reachable(node), "node {:?} is not reachable", node); + assert!(self.is_reachable(node), "node {node:?} is not reachable"); self.immediate_dominators[node].unwrap() } pub fn dominators(&self, node: Node) -> Iter<'_, Node> { - assert!(self.is_reachable(node), "node {:?} is not reachable", node); + assert!(self.is_reachable(node), "node {node:?} is not reachable"); Iter { dominators: self, node: Some(node) } } diff --git a/compiler/rustc_data_structures/src/graph/scc/mod.rs b/compiler/rustc_data_structures/src/graph/scc/mod.rs index b31092eca983..c8e66eb672cc 100644 --- a/compiler/rustc_data_structures/src/graph/scc/mod.rs +++ b/compiler/rustc_data_structures/src/graph/scc/mod.rs @@ -233,10 +233,9 @@ where .map(G::Node::new) .map(|node| match this.start_walk_from(node) { WalkReturn::Complete { scc_index } => scc_index, - WalkReturn::Cycle { min_depth } => panic!( - "`start_walk_node({:?})` returned cycle with depth {:?}", - node, min_depth - ), + WalkReturn::Cycle { min_depth } => { + panic!("`start_walk_node({node:?})` returned cycle with depth {min_depth:?}") + } }) .collect(); @@ -272,8 +271,7 @@ where NodeState::NotVisited => return None, NodeState::InCycleWith { parent } => panic!( - "`find_state` returned `InCycleWith({:?})`, which ought to be impossible", - parent + "`find_state` returned `InCycleWith({parent:?})`, which ought to be impossible" ), }) } @@ -369,7 +367,7 @@ where previous_node = previous; } // Only InCycleWith nodes were added to the reverse linked list. - other => panic!("Invalid previous link while compressing cycle: {:?}", other), + other => panic!("Invalid previous link while compressing cycle: {other:?}"), } debug!("find_state: parent_state = {:?}", node_state); @@ -394,7 +392,7 @@ where // NotVisited can not be part of a cycle since it should // have instead gotten explored. NodeState::NotVisited | NodeState::InCycleWith { .. } => { - panic!("invalid parent state: {:?}", node_state) + panic!("invalid parent state: {node_state:?}") } } } diff --git a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs index 3a268e4b4f43..4b6aa116520d 100644 --- a/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs +++ b/compiler/rustc_data_structures/src/obligation_forest/graphviz.rs @@ -30,7 +30,7 @@ impl ObligationForest { let counter = COUNTER.fetch_add(1, Ordering::AcqRel); - let file_path = dir.as_ref().join(format!("{:010}_{}.gv", counter, description)); + let file_path = dir.as_ref().join(format!("{counter:010}_{description}.gv")); let mut gv_file = BufWriter::new(File::create(file_path).unwrap()); @@ -47,7 +47,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest } fn node_id(&self, index: &Self::Node) -> dot::Id<'_> { - dot::Id::new(format!("obligation_{}", index)).unwrap() + dot::Id::new(format!("obligation_{index}")).unwrap() } fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> { diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 16296b224897..393f17390812 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -545,7 +545,7 @@ impl SelfProfiler { // length can behave as a source of entropy for heap addresses, when // ASLR is disabled and the heap is otherwise determinic. let pid: u32 = process::id(); - let filename = format!("{}-{:07}.rustc_profile", crate_name, pid); + let filename = format!("{crate_name}-{pid:07}.rustc_profile"); let path = output_directory.join(&filename); let profiler = Profiler::with_counter(&path, measureme::counters::Counter::by_name(counter_name)?)?; diff --git a/compiler/rustc_data_structures/src/small_c_str.rs b/compiler/rustc_data_structures/src/small_c_str.rs index 3a8ab8ff9911..719e4e3d9744 100644 --- a/compiler/rustc_data_structures/src/small_c_str.rs +++ b/compiler/rustc_data_structures/src/small_c_str.rs @@ -30,7 +30,7 @@ impl SmallCStr { SmallVec::from_vec(data) }; if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { - panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); + panic!("The string \"{s}\" cannot be converted into a CStr: {e}"); } SmallCStr { data } } @@ -39,7 +39,7 @@ impl SmallCStr { pub fn new_with_nul(s: &str) -> SmallCStr { let b = s.as_bytes(); if let Err(e) = ffi::CStr::from_bytes_with_nul(b) { - panic!("The string \"{}\" cannot be converted into a CStr: {}", s, e); + panic!("The string \"{s}\" cannot be converted into a CStr: {e}"); } SmallCStr { data: SmallVec::from_slice(s.as_bytes()) } } @@ -74,7 +74,7 @@ impl<'a> FromIterator<&'a str> for SmallCStr { iter.into_iter().flat_map(|s| s.as_bytes()).copied().collect::>(); data.push(0); if let Err(e) = ffi::CStr::from_bytes_with_nul(&data) { - panic!("The iterator {:?} cannot be converted into a CStr: {}", data, e); + panic!("The iterator {data:?} cannot be converted into a CStr: {e}"); } Self { data } } diff --git a/compiler/rustc_data_structures/src/vec_map.rs b/compiler/rustc_data_structures/src/vec_map.rs index 2417df66bb9d..d1a99bcaeb75 100644 --- a/compiler/rustc_data_structures/src/vec_map.rs +++ b/compiler/rustc_data_structures/src/vec_map.rs @@ -71,8 +71,7 @@ where // This should return just one element, otherwise it's a bug assert!( filter.next().is_none(), - "Collection {:#?} should have just one matching element", - self + "Collection {self:#?} should have just one matching element" ); Some(value) } diff --git a/compiler/rustc_driver/src/args.rs b/compiler/rustc_driver/src/args.rs index 01338359f1af..42c97cc6a9d7 100644 --- a/compiler/rustc_driver/src/args.rs +++ b/compiler/rustc_driver/src/args.rs @@ -25,7 +25,7 @@ pub fn arg_expand_all(at_args: &[String]) -> Vec { Ok(arg) => args.extend(arg), Err(err) => rustc_session::early_error( rustc_session::config::ErrorOutputType::default(), - &format!("Failed to load argument file: {}", err), + &format!("Failed to load argument file: {err}"), ), } } @@ -42,8 +42,8 @@ impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::Utf8Error(None) => write!(fmt, "Utf8 error"), - Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {}", path), - Error::IOError(path, err) => write!(fmt, "IO Error: {}: {}", path, err), + Error::Utf8Error(Some(path)) => write!(fmt, "Utf8 error in {path}"), + Error::IOError(path, err) => write!(fmt, "IO Error: {path}: {err}"), } } } diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 30179e978725..3cbe0052359b 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -486,11 +486,8 @@ impl Compilation { fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let upper_cased_code = code.to_ascii_uppercase(); - let normalised = if upper_cased_code.starts_with('E') { - upper_cased_code - } else { - format!("E{0:0>4}", code) - }; + let normalised = + if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") }; match registry.try_find_description(&normalised) { Ok(Some(description)) => { let mut is_in_code_block = false; @@ -513,14 +510,14 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { if io::stdout().is_terminal() { show_content_with_pager(&text); } else { - print!("{}", text); + print!("{text}"); } } Ok(None) => { - early_error(output, &format!("no extended information for {}", code)); + early_error(output, &format!("no extended information for {code}")); } Err(InvalidErrorCode) => { - early_error(output, &format!("{} is not a valid error code", code)); + early_error(output, &format!("{code} is not a valid error code")); } } } @@ -552,7 +549,7 @@ fn show_content_with_pager(content: &str) { // If pager fails for whatever reason, we should still print the content // to standard output if fallback_to_println { - print!("{}", content); + print!("{content}"); } } @@ -672,7 +669,7 @@ fn print_crate_info( ); let id = rustc_session::output::find_crate_name(sess, attrs, input); if *req == PrintRequest::CrateName { - println!("{}", id); + println!("{id}"); continue; } let crate_types = collect_crate_types(sess, attrs); @@ -704,7 +701,7 @@ fn print_crate_info( } if let Some(value) = value { - Some(format!("{}=\"{}\"", name, value)) + Some(format!("{name}=\"{value}\"")) } else { Some(name.to_string()) } @@ -713,7 +710,7 @@ fn print_crate_info( cfgs.sort(); for cfg in cfgs { - println!("{}", cfg); + println!("{cfg}"); } } CallingConventions => { @@ -739,7 +736,7 @@ fn print_crate_info( let stable = sess.target.options.supported_split_debuginfo.contains(split); let unstable_ok = sess.unstable_options(); if stable || unstable_ok { - println!("{}", split); + println!("{split}"); } } } @@ -776,14 +773,14 @@ pub fn version_at_macro_invocation( ) { let verbose = matches.opt_present("verbose"); - println!("{} {}", binary, version); + println!("{binary} {version}"); if verbose { - println!("binary: {}", binary); - println!("commit-hash: {}", commit_hash); - println!("commit-date: {}", commit_date); + println!("binary: {binary}"); + println!("commit-hash: {commit_hash}"); + println!("commit-date: {commit_date}"); println!("host: {}", config::host_triple()); - println!("release: {}", release); + println!("release: {release}"); let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); @@ -1037,7 +1034,7 @@ pub fn handle_options(args: &[String]) -> Option { .map(|&(name, ..)| ('C', name)) .chain(Z_OPTIONS.iter().map(|&(name, ..)| ('Z', name))) .find(|&(_, name)| *opt == name.replace('_', "-")) - .map(|(flag, _)| format!("{}. Did you mean `-{} {}`?", e, flag, opt)), + .map(|(flag, _)| format!("{e}. Did you mean `-{flag} {opt}`?")), _ => None, }; early_error(ErrorOutputType::default(), &msg.unwrap_or_else(|| e.to_string())); @@ -1148,7 +1145,7 @@ fn extra_compiler_flags() -> Option<(Vec, bool)> { } else { result.push(a.to_string()); match ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.iter().find(|s| option == **s) { - Some(s) => result.push(format!("{}=[REDACTED]", s)), + Some(s) => result.push(format!("{s}=[REDACTED]")), None => result.push(content), } } @@ -1246,7 +1243,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { let mut xs: Vec> = vec![ "the compiler unexpectedly panicked. this is a bug.".into(), - format!("we would appreciate a bug report: {}", bug_report_url).into(), + format!("we would appreciate a bug report: {bug_report_url}").into(), format!( "rustc {} running on {}", util::version_str!().unwrap_or("unknown_version"), @@ -1379,7 +1376,7 @@ pub fn main() -> ! { arg.into_string().unwrap_or_else(|arg| { early_error( ErrorOutputType::default(), - &format!("argument {} is not valid Unicode: {:?}", i, arg), + &format!("argument {i} is not valid Unicode: {arg:?}"), ) }) }) diff --git a/compiler/rustc_driver/src/pretty.rs b/compiler/rustc_driver/src/pretty.rs index f9b1316d2eb5..b2451bc730f7 100644 --- a/compiler/rustc_driver/src/pretty.rs +++ b/compiler/rustc_driver/src/pretty.rs @@ -360,7 +360,7 @@ fn get_source(input: &Input, sess: &Session) -> (String, FileName) { fn write_or_print(out: &str, ofile: Option<&Path>, sess: &Session) { match ofile { - None => print!("{}", out), + None => print!("{out}"), Some(p) => { if let Err(e) = std::fs::write(p, out) { sess.emit_fatal(UnprettyDumpFail { @@ -402,7 +402,7 @@ pub fn print_after_parsing( } AstTree(PpAstTreeMode::Normal) => { debug!("pretty printing AST tree"); - format!("{:#?}", krate) + format!("{krate:#?}") } _ => unreachable!(), }; @@ -446,7 +446,7 @@ pub fn print_after_hir_lowering<'tcx>( AstTree(PpAstTreeMode::Expanded) => { debug!("pretty-printing expanded AST"); - format!("{:#?}", krate) + format!("{krate:#?}") } Hir(s) => call_with_pp_support_hir(&s, tcx, move |annotation, hir_map| { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 6d8e78a0f185..ad85231860d2 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -70,7 +70,7 @@ impl std::fmt::Debug for AttributeGate { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match *self { Self::Gated(ref stab, name, expl, _) => { - write!(fmt, "Gated({:?}, {}, {})", stab, name, expl) + write!(fmt, "Gated({stab:?}, {name}, {expl})") } Self::Ungated => write!(fmt, "Ungated"), } diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index bdaa0ee88eba..8e2a13a6c0ab 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -120,7 +120,7 @@ fn find_lang_feature_issue(feature: Symbol) -> Option { .find(|t| t.name == feature); match found { Some(found) => found.issue, - None => panic!("feature `{}` is not declared anywhere", feature), + None => panic!("feature `{feature}` is not declared anywhere"), } } } diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs index 434f0a53b786..b70a55e89533 100644 --- a/compiler/rustc_graphviz/src/lib.rs +++ b/compiler/rustc_graphviz/src/lib.rs @@ -516,7 +516,7 @@ impl<'a> LabelText<'a> { match *self { LabelStr(ref s) => format!("\"{}\"", s.escape_default()), EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(s)), - HtmlStr(ref s) => format!("<{}>", s), + HtmlStr(ref s) => format!("<{s}>"), } } @@ -622,7 +622,7 @@ where if let Some(fontname) = options.iter().find_map(|option| { if let RenderOption::Fontname(fontname) = option { Some(fontname) } else { None } }) { - font = format!(r#"fontname="{}""#, fontname); + font = format!(r#"fontname="{fontname}""#); graph_attrs.push(&font[..]); content_attrs.push(&font[..]); } @@ -635,8 +635,8 @@ where if !(graph_attrs.is_empty() && content_attrs.is_empty()) { writeln!(w, r#" graph[{}];"#, graph_attrs.join(" "))?; let content_attrs_str = content_attrs.join(" "); - writeln!(w, r#" node[{}];"#, content_attrs_str)?; - writeln!(w, r#" edge[{}];"#, content_attrs_str)?; + writeln!(w, r#" node[{content_attrs_str}];"#)?; + writeln!(w, r#" edge[{content_attrs_str}];"#)?; } let mut text = Vec::new(); @@ -649,7 +649,7 @@ where write!(text, "{}", id.as_slice()).unwrap(); if !options.contains(&RenderOption::NoNodeLabels) { - write!(text, "[label={}]", escaped).unwrap(); + write!(text, "[label={escaped}]").unwrap(); } let style = g.node_style(n); @@ -678,7 +678,7 @@ where write!(text, "{} -> {}", source_id.as_slice(), target_id.as_slice()).unwrap(); if !options.contains(&RenderOption::NoEdgeLabels) { - write!(text, "[label={}]", escaped_label).unwrap(); + write!(text, "[label={escaped_label}]").unwrap(); } let style = g.edge_style(e); diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 149cf4ece37d..921039797869 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -597,8 +597,7 @@ impl Res { where Id: Debug, { - self.opt_def_id() - .unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {:?}", self)) + self.opt_def_id().unwrap_or_else(|| panic!("attempted .def_id() on invalid res: {self:?}")) } /// Return `Some(..)` with the `DefId` of this `Res` if it has a ID, else `None`. diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index dd37efb6983b..21cf214e47c5 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -53,9 +53,8 @@ impl DefPathTable { // // See the documentation for DefPathHash for more information. panic!( - "found DefPathHash collision between {:?} and {:?}. \ - Compilation cannot continue.", - def_path1, def_path2 + "found DefPathHash collision between {def_path1:?} and {def_path2:?}. \ + Compilation cannot continue." ); } @@ -224,7 +223,7 @@ impl DefPath { let mut s = String::with_capacity(self.data.len() * 16); for component in &self.data { - write!(s, "::{}", component).unwrap(); + write!(s, "::{component}").unwrap(); } s @@ -240,7 +239,7 @@ impl DefPath { for component in &self.data { s.extend(opt_delimiter); opt_delimiter = Some('-'); - write!(s, "{}", component).unwrap(); + write!(s, "{component}").unwrap(); } s @@ -433,7 +432,7 @@ impl fmt::Display for DefPathData { match self.name() { DefPathDataName::Named(name) => f.write_str(name.as_str()), // FIXME(#70334): this will generate legacy {{closure}}, {{impl}}, etc - DefPathDataName::Anon { namespace } => write!(f, "{{{{{}}}}}", namespace), + DefPathDataName::Anon { namespace } => write!(f, "{{{{{namespace}}}}}"), } } } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 5d05adfb5565..3b4add0cf4d4 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -119,7 +119,7 @@ impl HirId { impl fmt::Display for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?}", self) + write!(f, "{self:?}") } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 24a67cc14c4f..3e3af8395a11 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1268,7 +1268,7 @@ impl<'a> State<'a> { hir::InlineAsmOperand::In { reg, ref expr } => { s.word("in"); s.popen(); - s.word(format!("{}", reg)); + s.word(format!("{reg}")); s.pclose(); s.space(); s.print_expr(expr); @@ -1276,7 +1276,7 @@ impl<'a> State<'a> { hir::InlineAsmOperand::Out { reg, late, ref expr } => { s.word(if late { "lateout" } else { "out" }); s.popen(); - s.word(format!("{}", reg)); + s.word(format!("{reg}")); s.pclose(); s.space(); match expr { @@ -1287,7 +1287,7 @@ impl<'a> State<'a> { hir::InlineAsmOperand::InOut { reg, late, ref expr } => { s.word(if late { "inlateout" } else { "inout" }); s.popen(); - s.word(format!("{}", reg)); + s.word(format!("{reg}")); s.pclose(); s.space(); s.print_expr(expr); @@ -1295,7 +1295,7 @@ impl<'a> State<'a> { hir::InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => { s.word(if late { "inlateout" } else { "inout" }); s.popen(); - s.word(format!("{}", reg)); + s.word(format!("{reg}")); s.pclose(); s.space(); s.print_expr(in_expr); diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 686cb6dac496..15179392c88c 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -1091,7 +1091,7 @@ impl ToString for BitSet { assert!(mask <= 0xFF); let byte = word & mask; - result.push_str(&format!("{}{:02x}", sep, byte)); + result.push_str(&format!("{sep}{byte:02x}")); if remain <= 8 { break; diff --git a/compiler/rustc_index/src/interval.rs b/compiler/rustc_index/src/interval.rs index 3592fb33077d..d809740c6ab3 100644 --- a/compiler/rustc_index/src/interval.rs +++ b/compiler/rustc_index/src/interval.rs @@ -135,10 +135,7 @@ impl IntervalSet { }; debug_assert!( self.check_invariants(), - "wrong intervals after insert {:?}..={:?} to {:?}", - start, - end, - self + "wrong intervals after insert {start:?}..={end:?} to {self:?}" ); result } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 4c22ab68a568..7f761b005edd 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -90,8 +90,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option) -> CheckCfg { 'specs: for s in specs { let sess = ParseSess::with_silent_emitter(Some(format!( - "this error occurred on the command line: `--check-cfg={}`", - s + "this error occurred on the command line: `--check-cfg={s}`" ))); let filename = FileName::cfg_spec_source_code(&s); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 89d9450cf4e8..86d56385bc96 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -620,7 +620,7 @@ fn write_out_deps( // prevents `make` from spitting out an error if a file is later // deleted. For more info see #28735 for path in files { - writeln!(file, "{}:", path)?; + writeln!(file, "{path}:")?; } // Emit special comments with information about accessed environment variables. @@ -633,9 +633,9 @@ fn write_out_deps( envs.sort_unstable(); writeln!(file)?; for (k, v) in envs { - write!(file, "# env-dep:{}", k)?; + write!(file, "# env-dep:{k}")?; if let Some(v) = v { - write!(file, "={}", v)?; + write!(file, "={v}")?; } writeln!(file)?; } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 4142964a0dab..02a7756c8d45 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -205,13 +205,13 @@ pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( fn load_backend_from_dylib(path: &Path) -> MakeBackendFn { let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| { - let err = format!("couldn't load codegen backend {:?}: {}", path, err); + let err = format!("couldn't load codegen backend {path:?}: {err}"); early_error(ErrorOutputType::default(), &err); }); let backend_sym = unsafe { lib.get::(b"__rustc_codegen_backend") } .unwrap_or_else(|e| { - let err = format!("couldn't load codegen backend: {}", e); + let err = format!("couldn't load codegen backend: {e}"); early_error(ErrorOutputType::default(), &err); }); @@ -304,8 +304,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M .join("\n* "); let err = format!( "failed to find a `codegen-backends` folder \ - in the sysroot candidates:\n* {}", - candidates + in the sysroot candidates:\n* {candidates}" ); early_error(ErrorOutputType::default(), &err); }); @@ -325,7 +324,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M let expected_names = &[ format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")), - format!("rustc_codegen_{}", backend_name), + format!("rustc_codegen_{backend_name}"), ]; for entry in d.filter_map(|e| e.ok()) { let path = entry.path(); @@ -354,7 +353,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option, backend_name: &str) -> M match file { Some(ref s) => load_backend_from_dylib(s), None => { - let err = format!("unsupported builtin codegen backend `{}`", backend_name); + let err = format!("unsupported builtin codegen backend `{backend_name}`"); early_error(ErrorOutputType::default(), &err); } } @@ -389,7 +388,7 @@ pub(crate) fn check_attr_crate_type( BuiltinLintDiagnostics::UnknownCrateTypes( span, "did you mean".to_string(), - format!("\"{}\"", candidate), + format!("\"{candidate}\""), ), ); } else { diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 0b3c057345a6..9fe59a1d8261 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -58,7 +58,7 @@ fn restore_library_path() { /// Supposed to be used for all variables except those set for build scripts by cargo /// fn tracked_env_var_os + Display>(key: K) -> Option { - println!("cargo:rerun-if-env-changed={}", key); + println!("cargo:rerun-if-env-changed={key}"); env::var_os(key) } @@ -84,7 +84,7 @@ fn output(cmd: &mut Command) -> String { let output = match cmd.stderr(Stdio::inherit()).output() { Ok(status) => status, Err(e) => { - println!("\n\nfailed to execute command: {:?}\nerror: {}\n\n", cmd, e); + println!("\n\nfailed to execute command: {cmd:?}\nerror: {e}\n\n"); std::process::exit(1); } }; @@ -100,7 +100,7 @@ fn output(cmd: &mut Command) -> String { fn main() { for component in REQUIRED_COMPONENTS.iter().chain(OPTIONAL_COMPONENTS.iter()) { - println!("cargo:rustc-check-cfg=values(llvm_component,\"{}\")", component); + println!("cargo:rustc-check-cfg=values(llvm_component,\"{component}\")"); } if tracked_env_var_os("RUST_CHECK").is_some() { @@ -164,12 +164,12 @@ fn main() { for component in REQUIRED_COMPONENTS { if !components.contains(component) { - panic!("require llvm component {} but wasn't found", component); + panic!("require llvm component {component} but wasn't found"); } } for component in components.iter() { - println!("cargo:rustc-cfg=llvm_component=\"{}\"", component); + println!("cargo:rustc-cfg=llvm_component=\"{component}\""); } // Link in our own LLVM shims, compiled with the same flags as LLVM @@ -283,7 +283,7 @@ fn main() { } let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" }; - println!("cargo:rustc-link-lib={}={}", kind, name); + println!("cargo:rustc-link-lib={kind}={name}"); } // LLVM ldflags @@ -302,11 +302,11 @@ fn main() { println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target)); } } else if let Some(stripped) = lib.strip_prefix("-LIBPATH:") { - println!("cargo:rustc-link-search=native={}", stripped); + println!("cargo:rustc-link-search=native={stripped}"); } else if let Some(stripped) = lib.strip_prefix("-l") { - println!("cargo:rustc-link-lib={}", stripped); + println!("cargo:rustc-link-lib={stripped}"); } else if let Some(stripped) = lib.strip_prefix("-L") { - println!("cargo:rustc-link-search=native={}", stripped); + println!("cargo:rustc-link-search=native={stripped}"); } } @@ -318,9 +318,9 @@ fn main() { if let Some(s) = llvm_linker_flags { for lib in s.into_string().unwrap().split_whitespace() { if let Some(stripped) = lib.strip_prefix("-l") { - println!("cargo:rustc-link-lib={}", stripped); + println!("cargo:rustc-link-lib={stripped}"); } else if let Some(stripped) = lib.strip_prefix("-L") { - println!("cargo:rustc-link-search=native={}", stripped); + println!("cargo:rustc-link-search=native={stripped}"); } } } @@ -359,14 +359,14 @@ fn main() { let path = PathBuf::from(s); println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); if target.contains("windows") { - println!("cargo:rustc-link-lib=static:-bundle={}", stdcppname); + println!("cargo:rustc-link-lib=static:-bundle={stdcppname}"); } else { - println!("cargo:rustc-link-lib=static={}", stdcppname); + println!("cargo:rustc-link-lib=static={stdcppname}"); } } else if cxxflags.contains("stdlib=libc++") { println!("cargo:rustc-link-lib=c++"); } else { - println!("cargo:rustc-link-lib={}", stdcppname); + println!("cargo:rustc-link-lib={stdcppname}"); } } diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index ddf29c488c93..4cac88aff640 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -114,8 +114,7 @@ impl Display for Error { match self { Error::InvalidColorValue(value) => write!( formatter, - "invalid log color value '{}': expected one of always, never, or auto", - value, + "invalid log color value '{value}': expected one of always, never, or auto", ), Error::NonUnicodeColorValue => write!( formatter, diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs index 4612f54e4b17..2d62d5931638 100644 --- a/compiler/rustc_macros/src/diagnostics/error.rs +++ b/compiler/rustc_macros/src/diagnostics/error.rs @@ -76,11 +76,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic { let span = attr.span().unwrap(); let path = path_to_string(&attr.path); match meta { - Meta::Path(_) => span_err(span, &format!("`#[{}]` is not a valid attribute", path)), + Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")), Meta::NameValue(_) => { - span_err(span, &format!("`#[{} = ...]` is not a valid attribute", path)) + span_err(span, &format!("`#[{path} = ...]` is not a valid attribute")) } - Meta::List(_) => span_err(span, &format!("`#[{}(...)]` is not a valid attribute", path)), + Meta::List(_) => span_err(span, &format!("`#[{path}(...)]` is not a valid attribute")), } } @@ -107,7 +107,7 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag let meta = match nested { syn::NestedMeta::Meta(meta) => meta, syn::NestedMeta::Lit(_) => { - return span_err(span, &format!("`#[{}(\"...\")]` is not a valid attribute", name)); + return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute")); } }; @@ -115,13 +115,11 @@ pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diag let path = path_to_string(meta.path()); match meta { Meta::NameValue(..) => { - span_err(span, &format!("`#[{}({} = ...)]` is not a valid attribute", name, path)) - } - Meta::Path(..) => { - span_err(span, &format!("`#[{}({})]` is not a valid attribute", name, path)) + span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute")) } + Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")), Meta::List(..) => { - span_err(span, &format!("`#[{}({}(...))]` is not a valid attribute", name, path)) + span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute")) } } } diff --git a/compiler/rustc_macros/src/diagnostics/fluent.rs b/compiler/rustc_macros/src/diagnostics/fluent.rs index 3e447c94ef12..32338f9dfc5e 100644 --- a/compiler/rustc_macros/src/diagnostics/fluent.rs +++ b/compiler/rustc_macros/src/diagnostics/fluent.rs @@ -178,7 +178,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok opt: Default::default(), }; let dl = DisplayList::from(snippet); - eprintln!("{}\n", dl); + eprintln!("{dl}\n"); } continue; } @@ -265,7 +265,7 @@ pub(crate) fn fluent_messages(input: proc_macro::TokenStream) -> proc_macro::Tok Diagnostic::spanned( path_span, Level::Error, - format!("overrides existing {}: `{}`", kind, id), + format!("overrides existing {kind}: `{id}`"), ) .span_help(previous_defns[&id], "previously defined in this resource") .emit(); diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 767db3673225..baffd3cec9c5 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -198,8 +198,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { throw_span_err!( attr.span().unwrap(), &format!( - "diagnostic slug must be first argument of a `#[{}(...)]` attribute", - name + "diagnostic slug must be first argument of a `#[{name}(...)]` attribute" ) ); }; diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 4ff9c777ad85..6f52a3de1b15 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -322,7 +322,7 @@ pub(crate) trait HasFieldMap { None => { span_err( span.unwrap(), - &format!("`{}` doesn't refer to a field on this type", field), + &format!("`{field}` doesn't refer to a field on this type"), ) .emit(); quote! { @@ -603,8 +603,7 @@ impl SubdiagnosticKind { if suggestion_kind != SuggestionKind::Normal { invalid_attr(attr, &meta) .help(format!( - r#"Use `#[suggestion(..., style = "{}")]` instead"#, - suggestion_kind + r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"# )) .emit(); } @@ -621,8 +620,7 @@ impl SubdiagnosticKind { if suggestion_kind != SuggestionKind::Normal { invalid_attr(attr, &meta) .help(format!( - r#"Use `#[multipart_suggestion(..., style = "{}")]` instead"#, - suggestion_kind + r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"# )) .emit(); } diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs index 153473de6244..89ea89cf502e 100644 --- a/compiler/rustc_macros/src/newtype.rs +++ b/compiler/rustc_macros/src/newtype.rs @@ -41,7 +41,7 @@ impl Parse for Newtype { }; if let Some(old) = max.replace(literal.lit) { - panic!("Specified multiple max: {:?}", old); + panic!("Specified multiple max: {old:?}"); } false @@ -52,7 +52,7 @@ impl Parse for Newtype { }; if let Some(old) = debug_format.replace(literal.lit) { - panic!("Specified multiple debug format options: {:?}", old); + panic!("Specified multiple debug format options: {old:?}"); } false diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 789d83a0dd00..08e42a8a08f9 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -239,7 +239,7 @@ fn doc_comment_from_desc(list: &Punctuated) -> Result (TokenStream, Vec) { let mut check_dup = |span: Span, str: &str, errors: &mut Errors| { if let Some(prev_span) = keys.get(str) { - errors.error(span, format!("Symbol `{}` is duplicated", str)); + errors.error(span, format!("Symbol `{str}` is duplicated")); errors.error(*prev_span, "location of previous definition".to_string()); } else { keys.insert(str.to_string(), span); @@ -144,8 +144,8 @@ fn symbols_with_errors(input: TokenStream) -> (TokenStream, Vec) { let mut check_order = |span: Span, str: &str, errors: &mut Errors| { if let Some((prev_span, ref prev_str)) = prev_key { if str < prev_str { - errors.error(span, format!("Symbol `{}` must precede `{}`", str, prev_str)); - errors.error(prev_span, format!("location of previous symbol `{}`", prev_str)); + errors.error(span, format!("Symbol `{str}` must precede `{prev_str}`")); + errors.error(prev_span, format!("location of previous symbol `{prev_str}`")); } } prev_key = Some((span, str.to_string())); diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b34dc0df1e28..653f2b39d3e7 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -112,7 +112,7 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { writeln!(fmt, "resolved crates:")?; for (cnum, data) in self.0.iter_crate_data() { writeln!(fmt, " name: {}", data.name())?; - writeln!(fmt, " cnum: {}", cnum)?; + writeln!(fmt, " cnum: {cnum}")?; writeln!(fmt, " hash: {}", data.hash())?; writeln!(fmt, " reqd: {:?}", data.dep_kind())?; let CrateSource { dylib, rlib, rmeta } = data.source(); @@ -150,7 +150,7 @@ impl CStore { pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> { let cdata = self.metas[cnum] .as_ref() - .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)); + .unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}")); CrateMetadataRef { cdata, cstore: self } } diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1fd35adf1bd2..59869ee41737 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -45,7 +45,7 @@ pub fn find_native_static_library( for path in search_paths { for (prefix, suffix) in &formats { - let test = path.join(format!("{}{}{}", prefix, name, suffix)); + let test = path.join(format!("{prefix}{name}{suffix}")); if test.exists() { return test; } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 99d8225a4c39..143d8f2f1e18 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -462,7 +462,7 @@ impl<'a, 'tcx> Decodable> for SyntaxContext { .root .syntax_contexts .get(cdata, id) - .unwrap_or_else(|| panic!("Missing SyntaxContext {:?} for crate {:?}", id, cname)) + .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}")) .decode((cdata, sess)) }) } @@ -806,7 +806,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .def_span .get(self, index) - .unwrap_or_else(|| panic!("Missing span for {:?}", index)) + .unwrap_or_else(|| panic!("Missing span for {index:?}")) .decode((self, sess)) } @@ -1249,7 +1249,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .tables .proc_macro_quoted_spans .get(self, index) - .unwrap_or_else(|| panic!("Missing proc macro quoted span: {:?}", index)) + .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}")) .decode((self, sess)) } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index e167bbf57e62..cb451931dfe1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -230,7 +230,7 @@ provide! { tcx, def_id, other, cdata, .trait_impl_trait_tys .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) - .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id))) + .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) } visibility => { cdata.get_visibility(def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 40c94b372bbf..a6133f1b417a 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> Decodable> for DefPathHashMapRef<'static> let _ = d.read_raw_bytes(len); let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { - panic!("decode error: {}", e); + panic!("decode error: {e}"); }); DefPathHashMapRef::OwnedFromMetadata(inner) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 214a5842233b..0d9f216700fb 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx, I, T> Encodable> for LazyTable { impl<'a, 'tcx> Encodable> for CrateNum { fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) { if *self != LOCAL_CRATE && s.is_proc_macro { - panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self); + panic!("Attempted to encode non-local CrateNum {self:?} for proc-macro crate"); } s.emit_u32(self.as_u32()); } @@ -276,7 +276,7 @@ impl<'a, 'tcx> Encodable> for Span { // Introduce a new scope so that we drop the 'lock()' temporary match &*source_file.external_src.lock() { ExternalSource::Foreign { metadata_index, .. } => *metadata_index, - src => panic!("Unexpected external source {:?}", src), + src => panic!("Unexpected external source {src:?}"), } }; @@ -733,12 +733,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let prefix = "meta-stats"; let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64; - eprintln!("{} METADATA STATS", prefix); + eprintln!("{prefix} METADATA STATS"); eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size"); - eprintln!( - "{} ----------------------------------------------------------------", - prefix - ); + eprintln!("{prefix} ----------------------------------------------------------------"); for (label, size) in stats { eprintln!( "{} {:<23}{:>10} ({:4.1}%)", @@ -748,10 +745,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { perc(size) ); } - eprintln!( - "{} ----------------------------------------------------------------", - prefix - ); + eprintln!("{prefix} ----------------------------------------------------------------"); eprintln!( "{} {:<23}{:>10} (of which {:.1}% are zero bytes)", prefix, @@ -759,7 +753,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { to_readable_str(total_bytes), perc(zero_bytes) ); - eprintln!("{}", prefix); + eprintln!("{prefix}"); } root diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs index 209e6f7ac9fe..490be166a91d 100644 --- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs +++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs @@ -143,7 +143,7 @@ where ", " }; - write!(f, "{}", delim)?; + write!(f, "{delim}")?; idx.fmt_with(ctxt, f)?; first = false; } @@ -164,7 +164,7 @@ where ", " }; - write!(f, "{}", delim)?; + write!(f, "{delim}")?; idx.fmt_with(ctxt, f)?; first = false; } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index c9d5601f2074..96c42894b697 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -71,7 +71,7 @@ where fn graph_id(&self) -> dot::Id<'_> { let name = graphviz_safe_def_name(self.body.source.def_id()); - dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap() + dot::Id::new(format!("graph_for_def_id_{name}")).unwrap() } fn node_id(&self, n: &Self::Node) -> dot::Id<'_> { @@ -190,7 +190,7 @@ where " cellpadding=\"3\"", " sides=\"rb\"", ); - write!(w, r#""#, fmt = table_fmt)?; + write!(w, r#""#)?; // A + B: Block header match self.style { @@ -372,7 +372,7 @@ where write!(w, concat!("", r#"MIR"#,), fmt = fmt,)?; for name in state_column_names { - write!(w, "{name}", fmt = fmt, name = name)?; + write!(w, "{name}")?; } write!(w, "") @@ -394,18 +394,18 @@ where }; for (i, statement) in body[block].statements.iter().enumerate() { - let statement_str = format!("{:?}", statement); - let index_str = format!("{}", i); + let statement_str = format!("{statement:?}"); + let index_str = format!("{i}"); let after = next_in_dataflow_order(&mut afters); let before = befores.as_mut().map(next_in_dataflow_order); self.write_row(w, &index_str, &statement_str, |_this, w, fmt| { if let Some(before) = before { - write!(w, r#"{diff}"#, fmt = fmt, diff = before)?; + write!(w, r#"{before}"#)?; } - write!(w, r#"{diff}"#, fmt = fmt, diff = after) + write!(w, r#"{after}"#) })?; } @@ -421,10 +421,10 @@ where self.write_row(w, "T", &terminator_str, |_this, w, fmt| { if let Some(before) = before { - write!(w, r#"{diff}"#, fmt = fmt, diff = before)?; + write!(w, r#"{before}"#)?; } - write!(w, r#"{diff}"#, fmt = fmt, diff = after) + write!(w, r#"{after}"#) }) } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs index 9b053985bedf..5f22a418de86 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs @@ -129,13 +129,13 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> { fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result { write!(w, "MovePath {{")?; if let Some(parent) = self.parent { - write!(w, " parent: {:?},", parent)?; + write!(w, " parent: {parent:?},")?; } if let Some(first_child) = self.first_child { - write!(w, " first_child: {:?},", first_child)?; + write!(w, " first_child: {first_child:?},")?; } if let Some(next_sibling) = self.next_sibling { - write!(w, " next_sibling: {:?}", next_sibling)?; + write!(w, " next_sibling: {next_sibling:?}")?; } write!(w, " place: {:?} }}", self.place) } diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index fe5ee4011ab8..0522c657939f 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -920,7 +920,7 @@ fn debug_with_context( ) -> std::fmt::Result { for (local, place) in map.locals.iter_enumerated() { if let Some(place) = place { - debug_with_context_rec(*place, &format!("{:?}", local), new, old, map, f)?; + debug_with_context_rec(*place, &format!("{local:?}"), new, old, map, f)?; } } Ok(()) diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 59cc500a99da..b573df432505 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -526,7 +526,7 @@ fn collect_items_rec<'tcx>( let formatted_item = with_no_trimmed_paths!(starting_point.node.to_string()); tcx.sess.span_note_without_error( starting_point.span, - &format!("the above error was encountered while instantiating `{}`", formatted_item), + &format!("the above error was encountered while instantiating `{formatted_item}`"), ); } inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items); diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index f15cf54718e2..aa3227cac2de 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -50,7 +50,7 @@ impl IntoDiagnostic<'_> for UnusedGenericParams { // FIXME: I can figure out how to do a label with a fluent string with a fixed message, // or a label with a dynamic value in a hard-coded string, but I haven't figured out // how to combine the two. 😢 - diag.span_label(span, format!("generic parameter `{}` is unused", name)); + diag.span_label(span, format!("generic parameter `{name}` is unused")); } diag } diff --git a/compiler/rustc_monomorphize/src/partitioning/mod.rs b/compiler/rustc_monomorphize/src/partitioning/mod.rs index 97fbb458e792..fd6bcad18983 100644 --- a/compiler/rustc_monomorphize/src/partitioning/mod.rs +++ b/compiler/rustc_monomorphize/src/partitioning/mod.rs @@ -285,7 +285,7 @@ where use std::fmt::Write; let s = &mut String::new(); - let _ = writeln!(s, "{}", label); + let _ = writeln!(s, "{label}"); for cgu in cgus { let _ = writeln!(s, "CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate()); @@ -355,9 +355,8 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co } else { if mode_string != "lazy" { let message = format!( - "Unknown codegen-item collection mode '{}'. \ - Falling back to 'lazy' mode.", - mode_string + "Unknown codegen-item collection mode '{mode_string}'. \ + Falling back to 'lazy' mode." ); tcx.sess.warn(&message); } @@ -470,7 +469,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co item_keys.sort(); for item in item_keys { - println!("MONO_ITEM {}", item); + println!("MONO_ITEM {item}"); } } @@ -596,6 +595,6 @@ pub fn provide(providers: &mut Providers) { let (_, all) = tcx.collect_and_partition_mono_items(()); all.iter() .find(|cgu| cgu.name() == name) - .unwrap_or_else(|| panic!("failed to find cgu with name {:?}", name)) + .unwrap_or_else(|| panic!("failed to find cgu with name {name:?}")) }; } diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 6a4d2df1ead1..33e1f6ce3428 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -40,12 +40,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let new_size = tcx .layout_of(param_env.and(after_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) - .unwrap_or_else(|e| format!("Failed {:?}", e)); + .unwrap_or_else(|e| format!("Failed {e:?}")); let old_size = tcx .layout_of(param_env.and(before_feature_tys)) .map(|l| format!("{:?}", l.size.bytes())) - .unwrap_or_else(|e| format!("Failed {:?}", e)); + .unwrap_or_else(|e| format!("Failed {e:?}")); let closure_span = tcx.def_span(closure_def_id); let src_file = tcx.sess.source_map().span_to_filename(closure_span); @@ -54,7 +54,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In .source_map() .span_to_lines(closure_span) .map(|l| format!("{:?} {:?}", l.lines.first(), l.lines.last())) - .unwrap_or_else(|e| format!("{:?}", e)); + .unwrap_or_else(|e| format!("{e:?}")); if let Err(e) = writeln!( file, @@ -64,7 +64,7 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In src_file.prefer_local(), line_nos ) { - eprintln!("Error writing to file {}", e) + eprintln!("Error writing to file {e}") } } } diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 9f2aaca0acff..1eb227503f24 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -447,7 +447,7 @@ impl<'a> Parser<'a> { Some(pos) } else { let pos = self.to_span_index(pos); - let description = format!("expected `'}}'`, found `{:?}`", maybe); + let description = format!("expected `'}}'`, found `{maybe:?}`"); let label = "expected `}`".to_owned(); let (note, secondary_label) = if c == '}' { ( @@ -471,12 +471,12 @@ impl<'a> Parser<'a> { None } } else { - let description = format!("expected `{:?}` but string was terminated", c); + let description = format!("expected `{c:?}` but string was terminated"); // point at closing `"` let pos = self.input.len() - if self.append_newline { 1 } else { 0 }; let pos = self.to_span_index(pos); if c == '}' { - let label = format!("expected `{:?}`", c); + let label = format!("expected `{c:?}`"); let (note, secondary_label) = if c == '}' { ( Some( @@ -497,7 +497,7 @@ impl<'a> Parser<'a> { should_be_replaced_with_positional_argument: false, }); } else { - self.err(description, format!("expected `{:?}`", c), pos.to(pos)); + self.err(description, format!("expected `{c:?}`"), pos.to(pos)); } None } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index ef241c5398d4..e337cf16f22b 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -915,7 +915,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { if level != Level::Direct { error_msg.push_str(", "); } - error_msg.push_str(&format!("{:?}: {}", level, vis_str)); + error_msg.push_str(&format!("{level:?}: {vis_str}")); } } else { error_msg.push_str("not in the table"); diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 2bcfdab03c81..70c481fb0ee2 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -787,7 +787,7 @@ impl<'a, 'tcx> Decodable> for DefId { // which means that the definition with this hash is guaranteed to // still exist in the current compilation session. d.tcx.def_path_hash_to_def_id(def_path_hash, &mut || { - panic!("Failed to convert DefPathHash {:?}", def_path_hash) + panic!("Failed to convert DefPathHash {def_path_hash:?}") }) } } diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 535445e70bc1..6125ad4eff11 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -321,7 +321,7 @@ pub(crate) fn create_query_frame< ty::print::with_forced_impl_filename_line!(do_describe(tcx.tcx, key)) ); let description = - if tcx.sess.verbose() { format!("{} [{:?}]", description, name) } else { description }; + if tcx.sess.verbose() { format!("{description} [{name:?}]") } else { description }; let span = if kind == dep_graph::DepKind::def_span { // The `def_span` query is used to calculate `default_span`, // so exit to avoid infinite recursion. diff --git a/compiler/rustc_query_impl/src/profiling_support.rs b/compiler/rustc_query_impl/src/profiling_support.rs index 5f54bab9c314..4743170e9bfd 100644 --- a/compiler/rustc_query_impl/src/profiling_support.rs +++ b/compiler/rustc_query_impl/src/profiling_support.rs @@ -111,7 +111,7 @@ impl IntoSelfProfilingString for T { &self, builder: &mut QueryKeyStringBuilder<'_, '_>, ) -> StringId { - let s = format!("{:?}", self); + let s = format!("{self:?}"); builder.profiler.alloc_string(&s[..]) } } diff --git a/compiler/rustc_query_system/src/dep_graph/debug.rs b/compiler/rustc_query_system/src/dep_graph/debug.rs index f9f3169af69c..c2c9600f5552 100644 --- a/compiler/rustc_query_system/src/dep_graph/debug.rs +++ b/compiler/rustc_query_system/src/dep_graph/debug.rs @@ -29,7 +29,7 @@ impl DepNodeFilter { /// Tests whether `node` meets the filter, returning true if so. pub fn test(&self, node: &DepNode) -> bool { - let debug_str = format!("{:?}", node); + let debug_str = format!("{node:?}"); self.text.split('&').map(|s| s.trim()).all(|f| debug_str.contains(f)) } } @@ -46,7 +46,7 @@ impl EdgeFilter { pub fn new(test: &str) -> Result, Box> { let parts: Vec<_> = test.split("->").collect(); if parts.len() != 2 { - Err(format!("expected a filter like `a&b -> c&d`, not `{}`", test).into()) + Err(format!("expected a filter like `a&b -> c&d`, not `{test}`").into()) } else { Ok(EdgeFilter { source: DepNodeFilter::new(parts[0]), diff --git a/compiler/rustc_query_system/src/dep_graph/dep_node.rs b/compiler/rustc_query_system/src/dep_graph/dep_node.rs index d79c5816a9c4..9e1ca6ab515d 100644 --- a/compiler/rustc_query_system/src/dep_graph/dep_node.rs +++ b/compiler/rustc_query_system/src/dep_graph/dep_node.rs @@ -120,7 +120,7 @@ pub trait DepNodeParams: fmt::Debug + Sized { } fn to_debug_str(&self, _: Tcx) -> String { - format!("{:?}", self) + format!("{self:?}") } /// This method tries to recover the query key from the given `DepNode`, diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 0b1ff5d709fe..53c9da157371 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -316,10 +316,8 @@ impl DepGraph { assert!( !self.dep_node_exists(&key), "forcing query with already existing `DepNode`\n\ - - query-key: {:?}\n\ - - dep-node: {:?}", - arg, - key + - query-key: {arg:?}\n\ + - dep-node: {key:?}" ); let task_deps = if cx.dep_context().is_eval_always(key.kind) { @@ -365,8 +363,7 @@ impl DepGraph { debug_assert!( data.colors.get(prev_index).is_none(), "DepGraph::with_task() - Duplicate DepNodeColor \ - insertion for {:?}", - key + insertion for {key:?}" ); data.colors.insert(prev_index, color); @@ -447,7 +444,7 @@ impl DepGraph { TaskDepsRef::Allow(deps) => deps.lock(), TaskDepsRef::Ignore => return, TaskDepsRef::Forbid => { - panic!("Illegal read of: {:?}", dep_node_index) + panic!("Illegal read of: {dep_node_index:?}") } }; let task_deps = &mut *task_deps; @@ -824,8 +821,7 @@ impl DepGraph { debug_assert!( data.colors.get(prev_dep_node_index).is_none(), "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \ - insertion for {:?}", - dep_node + insertion for {dep_node:?}" ); if !side_effects.is_empty() { @@ -1164,7 +1160,7 @@ impl CurrentDepGraph { if let Some(fingerprint) = fingerprint { if fingerprint == prev_graph.fingerprint_by_index(prev_index) { if print_status { - eprintln!("[task::green] {:?}", key); + eprintln!("[task::green] {key:?}"); } // This is a green node: it existed in the previous compilation, @@ -1186,7 +1182,7 @@ impl CurrentDepGraph { (dep_node_index, Some((prev_index, DepNodeColor::Green(dep_node_index)))) } else { if print_status { - eprintln!("[task::red] {:?}", key); + eprintln!("[task::red] {key:?}"); } // This is a red node: it existed in the previous compilation, its query @@ -1209,7 +1205,7 @@ impl CurrentDepGraph { } } else { if print_status { - eprintln!("[task::unknown] {:?}", key); + eprintln!("[task::unknown] {key:?}"); } // This is a red node, effectively: it existed in the previous compilation @@ -1234,7 +1230,7 @@ impl CurrentDepGraph { } } else { if print_status { - eprintln!("[task::new] {:?}", key); + eprintln!("[task::new] {key:?}"); } let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO); diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs index a918328d4130..dfc1344f85c7 100644 --- a/compiler/rustc_query_system/src/dep_graph/serialized.rs +++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs @@ -270,17 +270,14 @@ impl> GraphEncoder { eprintln!("[incremental]"); eprintln!("[incremental] DepGraph Statistics"); - eprintln!("{}", SEPARATOR); + eprintln!("{SEPARATOR}"); eprintln!("[incremental]"); eprintln!("[incremental] Total Node Count: {}", status.total_node_count); eprintln!("[incremental] Total Edge Count: {}", status.total_edge_count); if cfg!(debug_assertions) { - eprintln!("[incremental] Total Edge Reads: {}", total_read_count); - eprintln!( - "[incremental] Total Duplicate Edge Reads: {}", - total_duplicate_read_count - ); + eprintln!("[incremental] Total Edge Reads: {total_read_count}"); + eprintln!("[incremental] Total Duplicate Edge Reads: {total_duplicate_read_count}"); } eprintln!("[incremental]"); @@ -288,7 +285,7 @@ impl> GraphEncoder { "[incremental] {:<36}| {:<17}| {:<12}| {:<17}|", "Node Kind", "Node Frequency", "Node Count", "Avg. Edge Count" ); - eprintln!("{}", SEPARATOR); + eprintln!("{SEPARATOR}"); for stat in stats { let node_kind_ratio = @@ -304,7 +301,7 @@ impl> GraphEncoder { ); } - eprintln!("{}", SEPARATOR); + eprintln!("{SEPARATOR}"); eprintln!("[incremental]"); } } diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index da1ac6a5fb22..b3b939eae88d 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -549,8 +549,7 @@ where // can be forced from `DepNode`. debug_assert!( !qcx.dep_context().fingerprint_style(dep_node.kind).reconstructible(), - "missing on-disk cache entry for {:?}", - dep_node + "missing on-disk cache entry for {dep_node:?}" ); } @@ -589,8 +588,7 @@ where { assert!( tcx.dep_graph().is_green(dep_node), - "fingerprint for green query instance not loaded from cache: {:?}", - dep_node, + "fingerprint for green query instance not loaded from cache: {dep_node:?}", ); let new_hash = hash_result.map_or(Fingerprint::ZERO, |f| { @@ -669,16 +667,16 @@ fn incremental_verify_ich_failed(sess: &Session, dep_node: DebugArg<'_>, result: sess.emit_err(crate::error::Reentrant); } else { let run_cmd = if let Some(crate_name) = &sess.opts.crate_name { - format!("`cargo clean -p {}` or `cargo clean`", crate_name) + format!("`cargo clean -p {crate_name}` or `cargo clean`") } else { "`cargo clean`".to_string() }; sess.emit_err(crate::error::IncrementCompilation { run_cmd, - dep_node: format!("{:?}", dep_node), + dep_node: format!("{dep_node:?}"), }); - panic!("Found unstable fingerprints for {:?}: {:?}", dep_node, result); + panic!("Found unstable fingerprints for {dep_node:?}: {result:?}"); } INSIDE_VERIFY_PANIC.with(|in_panic| in_panic.set(old_in_panic)); diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 221f65b66e6d..7c5e1427d1ed 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -303,7 +303,7 @@ impl DefId { // i.e. don't use closures. match self.as_local() { Some(local_def_id) => local_def_id, - None => panic!("DefId::expect_local: `{:?}` isn't local", self), + None => panic!("DefId::expect_local: `{self:?}` isn't local"), } } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 065d3660e500..b43183916bca 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -44,7 +44,7 @@ impl fmt::Display for Edition { Edition::Edition2021 => "2021", Edition::Edition2024 => "2024", }; - write!(f, "{}", s) + write!(f, "{s}") } } diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs index 4e70dfb61478..a9a9a3fbf9d8 100644 --- a/compiler/rustc_span/src/hygiene.rs +++ b/compiler/rustc_span/src/hygiene.rs @@ -110,7 +110,7 @@ fn assert_default_hashing_controls(ctx: &CTX, msg: &str) // Such configuration must not be used for metadata. HashingControls { hash_spans } if hash_spans == !ctx.unstable_opts_incremental_ignore_spans() => {} - other => panic!("Attempted hashing of {msg} with non-default HashingControls: {:?}", other), + other => panic!("Attempted hashing of {msg} with non-default HashingControls: {other:?}"), } } @@ -629,7 +629,7 @@ pub fn update_dollar_crate_names(mut get_name: impl FnMut(SyntaxContext) -> Symb pub fn debug_hygiene_data(verbose: bool) -> String { HygieneData::with(|data| { if verbose { - format!("{:#?}", data) + format!("{data:#?}") } else { let mut s = String::from("Expansions:"); let mut debug_expn_data = |(id, expn_data): (&ExpnId, &ExpnData)| { @@ -1067,9 +1067,9 @@ impl ExpnKind { match *self { ExpnKind::Root => kw::PathRoot.to_string(), ExpnKind::Macro(macro_kind, name) => match macro_kind { - MacroKind::Bang => format!("{}!", name), - MacroKind::Attr => format!("#[{}]", name), - MacroKind::Derive => format!("#[derive({})]", name), + MacroKind::Bang => format!("{name}!"), + MacroKind::Attr => format!("#[{name}]"), + MacroKind::Derive => format!("#[derive({name})]"), }, ExpnKind::AstPass(kind) => kind.descr().to_string(), ExpnKind::Desugaring(kind) => format!("desugaring of {}", kind.descr()), @@ -1466,11 +1466,7 @@ impl Decodable for SyntaxContext { /// collisions are only possible between `ExpnId`s within the same crate. fn update_disambiguator(expn_data: &mut ExpnData, mut ctx: impl HashStableContext) -> ExpnHash { // This disambiguator should not have been set yet. - assert_eq!( - expn_data.disambiguator, 0, - "Already set disambiguator for ExpnData: {:?}", - expn_data - ); + assert_eq!(expn_data.disambiguator, 0, "Already set disambiguator for ExpnData: {expn_data:?}"); assert_default_hashing_controls(&ctx, "ExpnData (disambiguator)"); let mut expn_hash = expn_data.hash_expn(&mut ctx); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index bee4b0a2332b..7e61f2f9f73c 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -329,7 +329,7 @@ impl fmt::Display for FileNameDisplay<'_> { ProcMacroSourceCode(_) => write!(fmt, ""), CfgSpec(_) => write!(fmt, ""), CliCrateAttr(_) => write!(fmt, ""), - Custom(ref s) => write!(fmt, "<{}>", s), + Custom(ref s) => write!(fmt, "<{s}>"), DocTest(ref path, _) => write!(fmt, "{}", path.display()), InlineAsm(_) => write!(fmt, ""), } @@ -1074,7 +1074,7 @@ impl NonNarrowChar { 0 => NonNarrowChar::ZeroWidth(pos), 2 => NonNarrowChar::Wide(pos), 4 => NonNarrowChar::Tab(pos), - _ => panic!("width {} given for non-narrow character", width), + _ => panic!("width {width} given for non-narrow character"), } } diff --git a/compiler/rustc_span/src/profiling.rs b/compiler/rustc_span/src/profiling.rs index f169007fab43..0ab890b9f012 100644 --- a/compiler/rustc_span/src/profiling.rs +++ b/compiler/rustc_span/src/profiling.rs @@ -27,7 +27,7 @@ impl SpannedEventArgRecorder for EventArgRecorder<'_> { if let Some(source_map) = &*session_globals.source_map.borrow() { source_map.span_to_embeddable_string(span) } else { - format!("{:?}", span) + format!("{span:?}") } }); self.record_arg(span_arg); diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index a59c9011ab21..23ff6b333f0d 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -175,7 +175,7 @@ impl SymbolPath { fn finish(mut self, hash: u64) -> String { self.finalize_pending_component(); // E = end name-sequence - let _ = write!(self.result, "17h{:016x}E", hash); + let _ = write!(self.result, "17h{hash:016x}E"); self.result } } @@ -227,7 +227,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { self = self.print_type(ty)?; self.write_str("; ")?; if let Some(size) = size.kind().try_to_bits(self.tcx().data_layout.pointer_size) { - write!(self, "{}", size)? + write!(self, "{size}")? } else if let ty::ConstKind::Param(param) = size.kind() { self = param.print(self)? } else { diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 62f44a48032e..547a59076602 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -269,8 +269,7 @@ fn compute_symbol_name<'tcx>( debug_assert!( rustc_demangle::try_demangle(&symbol).is_ok(), - "compute_symbol_name: `{}` cannot be demangled", - symbol + "compute_symbol_name: `{symbol}` cannot be demangled" ); symbol diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 150459ce0f53..c6899f8f244e 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -74,7 +74,7 @@ impl SymbolNamesTest<'_> { tcx.sess.emit_err(TestOutput { span: attr.span, kind: Kind::DemanglingAlt, - content: format!("{:#}", demangling), + content: format!("{demangling:#}"), }); } } diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index e9b85705086b..0759b95bd94c 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -126,11 +126,11 @@ fn encode_const<'tcx>( if value < zero { s.push('n') }; - let _ = write!(s, "{}", value); + let _ = write!(s, "{value}"); } fn push_unsigned_value(s: &mut String, value: T) { - let _ = write!(s, "{}", value); + let _ = write!(s, "{value}"); } if let Some(scalar_int) = c.kind().try_to_scalar_int() { diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 4285aa62cb96..9e8117c6a853 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -609,7 +609,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { bits = val.unsigned_abs(); } - let _ = write!(self.out, "{:x}_", bits); + let _ = write!(self.out, "{bits:x}_"); } // FIXME(valtrees): Remove the special case for `str` @@ -637,7 +637,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { // FIXME(eddyb) use a specialized hex-encoding loop. for byte in s.bytes() { - let _ = write!(self.out, "{:02x}", byte); + let _ = write!(self.out, "{byte:02x}"); } self.push("_"); diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index a5ffaebea0b9..280924bca415 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -177,12 +177,12 @@ impl Reg { 17..=32 => dl.i32_align.abi, 33..=64 => dl.i64_align.abi, 65..=128 => dl.i128_align.abi, - _ => panic!("unsupported integer: {:?}", self), + _ => panic!("unsupported integer: {self:?}"), }, RegKind::Float => match self.size.bits() { 32 => dl.f32_align.abi, 64 => dl.f64_align.abi, - _ => panic!("unsupported float: {:?}", self), + _ => panic!("unsupported float: {self:?}"), }, RegKind::Vector => dl.vector_align(self.size).abi, } @@ -642,7 +642,7 @@ impl fmt::Display for AdjustForForeignAbiError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Unsupported { arch, abi } => { - write!(f, "target architecture {:?} does not support `extern {}` ABI", arch, abi) + write!(f, "target architecture {arch:?} does not support `extern {abi}` ABI") } } } @@ -760,7 +760,7 @@ impl FromStr for Conv { "AmdGpuKernel" => Ok(Conv::AmdGpuKernel), "AvrInterrupt" => Ok(Conv::AvrInterrupt), "AvrNonBlockingInterrupt" => Ok(Conv::AvrNonBlockingInterrupt), - _ => Err(format!("'{}' is not a valid value for entry function call convetion.", s)), + _ => Err(format!("'{s}' is not a valid value for entry function call convetion.")), } } } diff --git a/compiler/rustc_target/src/asm/aarch64.rs b/compiler/rustc_target/src/asm/aarch64.rs index 62a0f9fb0347..28493c7700ff 100644 --- a/compiler/rustc_target/src/asm/aarch64.rs +++ b/compiler/rustc_target/src/asm/aarch64.rs @@ -195,6 +195,6 @@ impl AArch64InlineAsmReg { (modifier.unwrap_or('v'), self as u32 - Self::v0 as u32) }; assert!(index < 32); - write!(out, "{}{}", prefix, index) + write!(out, "{prefix}{index}") } } diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 0db3eb6fcac0..ec7429a30655 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -249,7 +249,7 @@ impl ArmInlineAsmReg { let index = self as u32 - Self::q0 as u32; assert!(index < 16); let index = index * 2 + (modifier == 'f') as u32; - write!(out, "d{}", index) + write!(out, "d{index}") } else { out.write_str(self.name()) } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 65d2cd64bf69..7f01f33d39c6 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -679,13 +679,13 @@ impl fmt::Display for InlineAsmType { Self::I128 => f.write_str("i128"), Self::F32 => f.write_str("f32"), Self::F64 => f.write_str("f64"), - Self::VecI8(n) => write!(f, "i8x{}", n), - Self::VecI16(n) => write!(f, "i16x{}", n), - Self::VecI32(n) => write!(f, "i32x{}", n), - Self::VecI64(n) => write!(f, "i64x{}", n), - Self::VecI128(n) => write!(f, "i128x{}", n), - Self::VecF32(n) => write!(f, "f32x{}", n), - Self::VecF64(n) => write!(f, "f64x{}", n), + Self::VecI8(n) => write!(f, "i8x{n}"), + Self::VecI16(n) => write!(f, "i16x{n}"), + Self::VecI32(n) => write!(f, "i32x{n}"), + Self::VecI64(n) => write!(f, "i64x{n}"), + Self::VecI128(n) => write!(f, "i128x{n}"), + Self::VecF32(n) => write!(f, "f32x{n}"), + Self::VecF64(n) => write!(f, "f64x{n}"), } } } diff --git a/compiler/rustc_target/src/asm/x86.rs b/compiler/rustc_target/src/asm/x86.rs index 238c365093f0..5eae07f141fc 100644 --- a/compiler/rustc_target/src/asm/x86.rs +++ b/compiler/rustc_target/src/asm/x86.rs @@ -357,28 +357,28 @@ impl X86InlineAsmReg { if self as u32 <= Self::dx as u32 { let root = ['a', 'b', 'c', 'd'][self as usize - Self::ax as usize]; match modifier.unwrap_or(reg_default_modifier) { - 'l' => write!(out, "{}l", root), - 'h' => write!(out, "{}h", root), - 'x' => write!(out, "{}x", root), - 'e' => write!(out, "e{}x", root), - 'r' => write!(out, "r{}x", root), + 'l' => write!(out, "{root}l"), + 'h' => write!(out, "{root}h"), + 'x' => write!(out, "{root}x"), + 'e' => write!(out, "e{root}x"), + 'r' => write!(out, "r{root}x"), _ => unreachable!(), } } else if self as u32 <= Self::di as u32 { let root = self.name(); match modifier.unwrap_or(reg_default_modifier) { - 'l' => write!(out, "{}l", root), - 'x' => write!(out, "{}", root), - 'e' => write!(out, "e{}", root), - 'r' => write!(out, "r{}", root), + 'l' => write!(out, "{root}l"), + 'x' => write!(out, "{root}"), + 'e' => write!(out, "e{root}"), + 'r' => write!(out, "r{root}"), _ => unreachable!(), } } else if self as u32 <= Self::r15 as u32 { let root = self.name(); match modifier.unwrap_or(reg_default_modifier) { - 'l' => write!(out, "{}b", root), - 'x' => write!(out, "{}w", root), - 'e' => write!(out, "{}d", root), + 'l' => write!(out, "{root}b"), + 'x' => write!(out, "{root}w"), + 'e' => write!(out, "{root}d"), 'r' => out.write_str(root), _ => unreachable!(), } @@ -387,15 +387,15 @@ impl X86InlineAsmReg { } else if self as u32 <= Self::xmm15 as u32 { let prefix = modifier.unwrap_or('x'); let index = self as u32 - Self::xmm0 as u32; - write!(out, "{}{}", prefix, index) + write!(out, "{prefix}{index}") } else if self as u32 <= Self::ymm15 as u32 { let prefix = modifier.unwrap_or('y'); let index = self as u32 - Self::ymm0 as u32; - write!(out, "{}{}", prefix, index) + write!(out, "{prefix}{index}") } else if self as u32 <= Self::zmm31 as u32 { let prefix = modifier.unwrap_or('z'); let index = self as u32 - Self::zmm0 as u32; - write!(out, "{}{}", prefix, index) + write!(out, "{prefix}{index}") } else { out.write_str(self.name()) } diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index 44644c4733e8..5c6dcc0aba9c 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -76,7 +76,7 @@ impl Arch { fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs { let platform_name: StaticCow = match abi { - "sim" => format!("{}-simulator", os).into(), + "sim" => format!("{os}-simulator").into(), "macabi" => "mac-catalyst".into(), _ => os.into(), }; @@ -193,7 +193,7 @@ fn macos_deployment_target(arch: Arch) -> (u32, u32) { fn macos_lld_platform_version(arch: Arch) -> String { let (major, minor) = macos_deployment_target(arch); - format!("{}.{}", major, minor) + format!("{major}.{minor}") } pub fn macos_llvm_target(arch: Arch) -> String { @@ -252,7 +252,7 @@ pub fn ios_llvm_target(arch: Arch) -> String { fn ios_lld_platform_version() -> String { let (major, minor) = ios_deployment_target(); - format!("{}.{}", major, minor) + format!("{major}.{minor}") } pub fn ios_sim_llvm_target(arch: Arch) -> String { @@ -266,7 +266,7 @@ fn tvos_deployment_target() -> (u32, u32) { fn tvos_lld_platform_version() -> String { let (major, minor) = tvos_deployment_target(); - format!("{}.{}", major, minor) + format!("{major}.{minor}") } fn watchos_deployment_target() -> (u32, u32) { @@ -275,7 +275,7 @@ fn watchos_deployment_target() -> (u32, u32) { fn watchos_lld_platform_version() -> String { let (major, minor) = watchos_deployment_target(); - format!("{}.{}", major, minor) + format!("{major}.{minor}") } pub fn watchos_sim_llvm_target(arch: Arch) -> String { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b7ec1612e8ec..5bbd86bb5b9b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -840,7 +840,7 @@ impl fmt::Display for SanitizerSet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut first = true; for s in *self { - let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {:?}", s)); + let name = s.as_str().unwrap_or_else(|| panic!("unrecognized sanitizer {s:?}")); if !first { f.write_str(", ")?; } @@ -2074,7 +2074,7 @@ impl Target { let mut get_req_field = |name: &str| { obj.remove(name) .and_then(|j| j.as_str().map(str::to_string)) - .ok_or_else(|| format!("Field {} in target specification is required", name)) + .ok_or_else(|| format!("Field {name} in target specification is required")) }; let mut base = Target { @@ -2480,7 +2480,7 @@ impl Target { if let Some(s) = fp.as_str() { base.frame_pointer = s .parse() - .map_err(|()| format!("'{}' is not a valid value for frame-pointer", s))?; + .map_err(|()| format!("'{s}' is not a valid value for frame-pointer"))?; } else { incorrect_type.push("frame-pointer".into()) } @@ -2672,7 +2672,7 @@ impl Target { return load_file(&p); } - Err(format!("Could not find specification for target {:?}", target_triple)) + Err(format!("Could not find specification for target {target_triple:?}")) } TargetTriple::TargetJson { ref contents, .. } => { let obj = serde_json::from_str(contents).map_err(|e| e.to_string())?; @@ -2936,7 +2936,7 @@ impl TargetTriple { let contents = std::fs::read_to_string(&canonicalized_path).map_err(|err| { io::Error::new( io::ErrorKind::InvalidInput, - format!("target path {:?} is not a valid file: {}", canonicalized_path, err), + format!("target path {canonicalized_path:?} is not a valid file: {err}"), ) })?; let triple = canonicalized_path @@ -2971,7 +2971,7 @@ impl TargetTriple { let mut hasher = DefaultHasher::new(); content.hash(&mut hasher); let hash = hasher.finish(); - format!("{}-{}", triple, hash) + format!("{triple}-{hash}") } } } diff --git a/compiler/rustc_target/src/spec/solid_base.rs b/compiler/rustc_target/src/spec/solid_base.rs index c585a6cd58ea..eaf72b7616c7 100644 --- a/compiler/rustc_target/src/spec/solid_base.rs +++ b/compiler/rustc_target/src/spec/solid_base.rs @@ -3,7 +3,7 @@ use crate::spec::TargetOptions; pub fn opts(kernel: &str) -> TargetOptions { TargetOptions { - os: format!("solid_{}", kernel).into(), + os: format!("solid_{kernel}").into(), vendor: "kmc".into(), executables: false, frame_pointer: FramePointer::NonLeaf, diff --git a/compiler/rustc_traits/src/dropck_outlives.rs b/compiler/rustc_traits/src/dropck_outlives.rs index 3f661ce69235..481b56e111ea 100644 --- a/compiler/rustc_traits/src/dropck_outlives.rs +++ b/compiler/rustc_traits/src/dropck_outlives.rs @@ -189,7 +189,7 @@ fn dtorck_constraint_for_ty<'tcx>( tcx.sess.delay_span_bug( span, - &format!("upvar_tys for closure not found. Expected capture information for closure {}", ty,), + &format!("upvar_tys for closure not found. Expected capture information for closure {ty}",), ); return Err(NoSolution); } @@ -231,7 +231,7 @@ fn dtorck_constraint_for_ty<'tcx>( // be fully resolved. tcx.sess.delay_span_bug( span, - &format!("upvar_tys for generator not found. Expected capture information for generator {}", ty,), + &format!("upvar_tys for generator not found. Expected capture information for generator {ty}",), ); return Err(NoSolution); } diff --git a/compiler/rustc_traits/src/normalize_erasing_regions.rs b/compiler/rustc_traits/src/normalize_erasing_regions.rs index 6e6bc62a040d..5cad2c2ccb0f 100644 --- a/compiler/rustc_traits/src/normalize_erasing_regions.rs +++ b/compiler/rustc_traits/src/normalize_erasing_regions.rs @@ -47,7 +47,7 @@ fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<'tcx> + PartialEq + // us a test case. debug_assert_eq!(normalized_value, resolved_value); let erased = infcx.tcx.erase_regions(resolved_value); - debug_assert!(!erased.needs_infer(), "{:?}", erased); + debug_assert!(!erased.needs_infer(), "{erased:?}"); Ok(erased) } Err(NoSolution) => Err(NoSolution), diff --git a/compiler/rustc_transmute/src/layout/mod.rs b/compiler/rustc_transmute/src/layout/mod.rs index 07035ebdfb16..f8d05bc89d26 100644 --- a/compiler/rustc_transmute/src/layout/mod.rs +++ b/compiler/rustc_transmute/src/layout/mod.rs @@ -24,7 +24,7 @@ impl fmt::Debug for Byte { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self { Self::Uninit => f.write_str("??u8"), - Self::Init(b) => write!(f, "{:#04x}u8", b), + Self::Init(b) => write!(f, "{b:#04x}u8"), } } } diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index dd36a5c7a216..fed070408f39 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -718,9 +718,9 @@ impl fmt::Debug for InferTy { TyVar(ref v) => v.fmt(f), IntVar(ref v) => v.fmt(f), FloatVar(ref v) => v.fmt(f), - FreshTy(v) => write!(f, "FreshTy({:?})", v), - FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), - FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v), + FreshTy(v) => write!(f, "FreshTy({v:?})"), + FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"), + FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"), } } } @@ -743,9 +743,9 @@ impl fmt::Display for InferTy { TyVar(_) => write!(f, "_"), IntVar(_) => write!(f, "{}", "{integer}"), FloatVar(_) => write!(f, "{}", "{float}"), - FreshTy(v) => write!(f, "FreshTy({})", v), - FreshIntTy(v) => write!(f, "FreshIntTy({})", v), - FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v), + FreshTy(v) => write!(f, "FreshTy({v})"), + FreshIntTy(v) => write!(f, "FreshIntTy({v})"), + FreshFloatTy(v) => write!(f, "FreshFloatTy({v})"), } } } diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs index f30ae82d7cdd..b944cbd698d1 100644 --- a/compiler/rustc_type_ir/src/sty.rs +++ b/compiler/rustc_type_ir/src/sty.rs @@ -1028,10 +1028,10 @@ impl hash::Hash for RegionKind { impl fmt::Debug for RegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - ReEarlyBound(data) => write!(f, "ReEarlyBound({:?})", data), + ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"), ReLateBound(binder_id, bound_region) => { - write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) + write!(f, "ReLateBound({binder_id:?}, {bound_region:?})") } ReFree(fr) => fr.fmt(f), @@ -1040,7 +1040,7 @@ impl fmt::Debug for RegionKind { ReVar(vid) => vid.fmt(f), - RePlaceholder(placeholder) => write!(f, "RePlaceholder({:?})", placeholder), + RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"), ReErased => f.write_str("ReErased"), } From 0de182a5810d6c732eb2bcd40d1b98eef884dd27 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 5 Jan 2023 10:59:21 -0700 Subject: [PATCH 166/223] rustdoc: remove legacy user-select CSS According to [caniuse], the only supported browser that requires the vendor prefix, as defined in [RFC 1985], is Safari. * The last version of Chrome that required a vendor prefix was version 53. The current version is 108. * Firefox 68 is the last version that required a vendor prefix. The [current Firefox ESR] is version 102. * The current version of Safari for Mac and iOS still requires a prefix. * The last version of Edge that required a vendor frefix was 18. The current version of Edge is 108. * UCAndroid support is unknown, but if it still requires a vendor prefix, it's more likely to be `-webkit-` than `-moz-` or `-ms-`, since they would want to emulate iOS for compatibility. [caniuse]: https://caniuse.com/?search=user-select [RFC 1985]: https://rust-lang.github.io/rfcs/1985-tiered-browser-support.html [current Firefox ESR]: https://wiki.mozilla.org/Releases --- src/librustdoc/html/static/css/rustdoc.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index cdc077e26bf2..0e609a6f9706 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -538,8 +538,6 @@ ul.block, .block li { overflow: initial; text-align: right; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; user-select: none; padding: 14px 8px; color: var(--src-line-numbers-span-color); From f2ad85a930539986517747729df6082553d195f8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 5 Jan 2023 11:07:11 -0800 Subject: [PATCH 167/223] Fix error-index redirect to work with back button. --- src/tools/error_index_generator/main.rs | 11 +++++++---- src/tools/error_index_generator/redirect.js | 10 +++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 1bde8e007826..2ccb6b81233f 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -98,8 +98,7 @@ fn add_rust_attribute_on_codeblock(explanation: &str) -> String { fn render_html(output_path: &Path) -> Result<(), Box> { let mut introduction = format!( - " -# Rust error codes index + "# Rust error codes index This page lists all the error codes emitted by the Rust compiler. @@ -149,7 +148,12 @@ This page lists all the error codes emitted by the Rust compiler. book.book.sections.push(BookItem::Chapter(chapter)); book.build()?; - // We can't put this content into another file, otherwise `mbdbook` will also put it into the + // The error-index used to be generated manually (without mdbook), and the + // index was located at the top level. Now that it is generated with + // mdbook, error-index.html has moved to error_codes/error-index.html. + // This adds a redirect so that old links go to the new location. + // + // We can't put this content into another file, otherwise `mdbook` will also put it into the // output directory, making a duplicate. fs::write( output_path.join("error-index.html"), @@ -163,7 +167,6 @@ This page lists all the error codes emitted by the Rust compiler.

If you are not automatically redirected to the error code index, please here. - "#, )?; diff --git a/src/tools/error_index_generator/redirect.js b/src/tools/error_index_generator/redirect.js index 8c907f5795d3..c80cbf297aff 100644 --- a/src/tools/error_index_generator/redirect.js +++ b/src/tools/error_index_generator/redirect.js @@ -3,14 +3,10 @@ let code = window.location.hash.replace(/^#/, ''); // We have to make sure this pattern matches to avoid inadvertently creating an // open redirect. - if (!/^E[0-9]+$/.test(code)) { + if (/^E[0-9]+$/.test(code)) { + window.location.replace('./error_codes/' + code + '.html'); return; } - if (window.location.pathname.indexOf("/error_codes/") !== -1) { - // We're not at the top level, so we don't prepend with "./error_codes/". - window.location = './' + code + '.html'; - } else { - window.location = './error_codes/' + code + '.html'; - } } + window.location.replace('./error_codes/error-index.html'); })() From 72c3082aab3e2df801deeefcc65c7469d93274ca Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 5 Jan 2023 06:44:11 -0800 Subject: [PATCH 168/223] error-index: Don't generate 404 instead of removing it. --- src/tools/error_index_generator/book_config.toml | 1 + src/tools/error_index_generator/main.rs | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tools/error_index_generator/book_config.toml b/src/tools/error_index_generator/book_config.toml index 885100ae3a44..2701ad917bb0 100644 --- a/src/tools/error_index_generator/book_config.toml +++ b/src/tools/error_index_generator/book_config.toml @@ -7,6 +7,7 @@ src = "" git-repository-url = "https://github.com/rust-lang/rust/" additional-css = ["error-index.css"] additional-js = ["error-index.js"] +input-404 = "" [output.html.search] enable = true diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index 2ccb6b81233f..98eda97e236c 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -171,9 +171,6 @@ This page lists all the error codes emitted by the Rust compiler. "#, )?; - // No need for a 404 file, it's already handled by the server. - fs::remove_file(output_path.join("error_codes/404.html"))?; - Ok(()) } From 5112f0281d4bff402843bef88dbc13b33358cc1c Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 3 Jan 2023 19:28:28 +0100 Subject: [PATCH 169/223] Shrink `ParseResult` in the hot path. A recent PR increased the size, which caused regressions. This uses the existing generic infrastructure to differentiate between the hot path and the diagnostics path. --- compiler/rustc_expand/src/mbe/diagnostics.rs | 25 +++++++- compiler/rustc_expand/src/mbe/macro_parser.rs | 26 ++++---- compiler/rustc_expand/src/mbe/macro_rules.rs | 60 ++++++++++++++----- 3 files changed, 81 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 3a38d7a96696..f469b2daef5e 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -114,6 +114,12 @@ impl BestFailure { } impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, 'matcher> { + type Failure = (Token, usize, &'static str); + + fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure { + (tok, position, msg) + } + fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc) { if self.remaining_matcher.is_none() || (parser.has_no_remaining_items_for_step() && *matcher != MatcherLoc::Eof) @@ -122,7 +128,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, } } - fn after_arm(&mut self, result: &NamedParseResult) { + fn after_arm(&mut self, result: &NamedParseResult) { match result { Success(_) => { // Nonterminal parser recovery might turn failed matches into successful ones, @@ -132,7 +138,7 @@ impl<'a, 'cx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'a, 'cx, "should not collect detailed info for successful macro match", ); } - Failure(token, approx_position, msg) => { + Failure((token, approx_position, msg)) => { debug!(?token, ?msg, "a new failure of an arm"); if self @@ -175,6 +181,21 @@ impl<'a, 'cx> CollectTrackerAndEmitter<'a, 'cx, '_> { } } +/// Currently used by macro_rules! compilation to extract a little information from the `Failure` case. +pub struct FailureForwarder; + +impl<'matcher> Tracker<'matcher> for FailureForwarder { + type Failure = (Token, usize, &'static str); + + fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure { + (tok, position, msg) + } + + fn description() -> &'static str { + "failure-forwarder" + } +} + pub(super) fn emit_frag_parse_err( mut e: DiagnosticBuilder<'_, rustc_errors::ErrorGuaranteed>, parser: &Parser<'_>, diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index df1c1834c1dc..2e199541b92b 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -305,13 +305,13 @@ enum EofMatcherPositions { } /// Represents the possible results of an attempted parse. -pub(crate) enum ParseResult { +pub(crate) enum ParseResult { /// Parsed successfully. Success(T), /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. /// The usize is the approximate position of the token in the input token stream. - Failure(Token, usize, &'static str), + Failure(F), /// Fatal error (malformed macro?). Abort compilation. Error(rustc_span::Span, String), ErrorReported(ErrorGuaranteed), @@ -320,7 +320,7 @@ pub(crate) enum ParseResult { /// A `ParseResult` where the `Success` variant contains a mapping of /// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping /// of metavars to the token trees they bind to. -pub(crate) type NamedParseResult = ParseResult; +pub(crate) type NamedParseResult = ParseResult; /// Contains a mapping of `MacroRulesNormalizedIdent`s to `NamedMatch`es. /// This represents the mapping of metavars to the token trees they bind to. @@ -458,7 +458,7 @@ impl TtParser { token: &Token, approx_position: usize, track: &mut T, - ) -> Option { + ) -> Option> { // Matcher positions that would be valid if the macro invocation was over now. Only // modified if `token == Eof`. let mut eof_mps = EofMatcherPositions::None; @@ -595,14 +595,14 @@ impl TtParser { EofMatcherPositions::Multiple => { Error(token.span, "ambiguity: multiple successful parses".to_string()) } - EofMatcherPositions::None => Failure( + EofMatcherPositions::None => Failure(T::build_failure( Token::new( token::Eof, if token.span.is_dummy() { token.span } else { token.span.shrink_to_hi() }, ), approx_position, "missing tokens in macro arguments", - ), + )), }) } else { None @@ -615,7 +615,7 @@ impl TtParser { parser: &mut Cow<'_, Parser<'_>>, matcher: &'matcher [MatcherLoc], track: &mut T, - ) -> NamedParseResult { + ) -> NamedParseResult { // A queue of possible matcher positions. We initialize it with the matcher position in // which the "dot" is before the first token of the first token tree in `matcher`. // `parse_tt_inner` then processes all of these possible matcher positions and produces @@ -648,11 +648,11 @@ impl TtParser { (0, 0) => { // There are no possible next positions AND we aren't waiting for the black-box // parser: syntax error. - return Failure( + return Failure(T::build_failure( parser.token.clone(), parser.approx_token_stream_pos(), "no rules expected this token in macro call", - ); + )); } (_, 0) => { @@ -711,11 +711,11 @@ impl TtParser { } } - fn ambiguity_error( + fn ambiguity_error( &self, matcher: &[MatcherLoc], token_span: rustc_span::Span, - ) -> NamedParseResult { + ) -> NamedParseResult { let nts = self .bb_mps .iter() @@ -741,11 +741,11 @@ impl TtParser { ) } - fn nameize>( + fn nameize, F>( &self, matcher: &[MatcherLoc], mut res: I, - ) -> NamedParseResult { + ) -> NamedParseResult { // Make that each metavar has _exactly one_ binding. If so, insert the binding into the // `NamedParseResult`. Otherwise, it's an error. let mut ret_val = FxHashMap::default(); diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index fbb806fe81b2..c0489f686336 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -141,31 +141,40 @@ fn trace_macros_note(cx_expansions: &mut FxIndexMap>, sp: Span } pub(super) trait Tracker<'matcher> { + /// The contents of `ParseResult::Failure`. + type Failure; + + /// Arm failed to match. If the token is `token::Eof`, it indicates an unexpected + /// end of macro invocation. Otherwise, it indicates that no rules expected the given token. + /// The usize is the approximate position of the token in the input token stream. + fn build_failure(tok: Token, position: usize, msg: &'static str) -> Self::Failure; + /// This is called before trying to match next MatcherLoc on the current token. - fn before_match_loc(&mut self, parser: &TtParser, matcher: &'matcher MatcherLoc); + fn before_match_loc(&mut self, _parser: &TtParser, _matcher: &'matcher MatcherLoc) {} /// This is called after an arm has been parsed, either successfully or unsuccessfully. When this is called, /// `before_match_loc` was called at least once (with a `MatcherLoc::Eof`). - fn after_arm(&mut self, result: &NamedParseResult); + fn after_arm(&mut self, _result: &NamedParseResult) {} /// For tracing. fn description() -> &'static str; - fn recovery() -> Recovery; + fn recovery() -> Recovery { + Recovery::Forbidden + } } /// A noop tracker that is used in the hot path of the expansion, has zero overhead thanks to monomorphization. pub(super) struct NoopTracker; impl<'matcher> Tracker<'matcher> for NoopTracker { - fn before_match_loc(&mut self, _: &TtParser, _: &'matcher MatcherLoc) {} - fn after_arm(&mut self, _: &NamedParseResult) {} + type Failure = (); + + fn build_failure(_tok: Token, _position: usize, _msg: &'static str) -> Self::Failure {} + fn description() -> &'static str { "none" } - fn recovery() -> Recovery { - Recovery::Forbidden - } } /// Expands the rules based macro defined by `lhses` and `rhses` for a given @@ -326,8 +335,8 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>( return Ok((i, named_matches)); } - Failure(_, reached_position, _) => { - trace!(%reached_position, "Failed to match arm, trying the next one"); + Failure(_) => { + trace!("Failed to match arm, trying the next one"); // Try the next arm. } Error(_, _) => { @@ -381,11 +390,13 @@ pub fn compile_declarative_macro( let rhs_nm = Ident::new(sym::rhs, def.span); let tt_spec = Some(NonterminalKind::TT); - // Parse the macro_rules! invocation - let (macro_rules, body) = match &def.kind { - ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.tokens.clone()), + let macro_def = match &def.kind { + ast::ItemKind::MacroDef(def) => def, _ => unreachable!(), }; + let macro_rules = macro_def.macro_rules; + + // Parse the macro_rules! invocation // The pattern that macro_rules matches. // The grammar for macro_rules! is: @@ -426,13 +437,32 @@ pub fn compile_declarative_macro( // Convert it into `MatcherLoc` form. let argument_gram = mbe::macro_parser::compute_locs(&argument_gram); - let parser = Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS); + let create_parser = || { + let body = macro_def.body.tokens.clone(); + Parser::new(&sess.parse_sess, body, true, rustc_parse::MACRO_ARGUMENTS) + }; + + let parser = create_parser(); let mut tt_parser = TtParser::new(Ident::with_dummy_span(if macro_rules { kw::MacroRules } else { kw::Macro })); let argument_map = match tt_parser.parse_tt(&mut Cow::Owned(parser), &argument_gram, &mut NoopTracker) { Success(m) => m, - Failure(token, _, msg) => { + Failure(()) => { + // The fast `NoopTracker` doesn't have any info on failure, so we need to retry it with another one + // that gives us the information we need. + // For this we need to reclone the macro body as the previous parser consumed it. + let retry_parser = create_parser(); + + let parse_result = tt_parser.parse_tt( + &mut Cow::Owned(retry_parser), + &argument_gram, + &mut diagnostics::FailureForwarder, + ); + let Failure((token, _, msg)) = parse_result else { + unreachable!("matcher returned something other than Failure after retry"); + }; + let s = parse_failure_msg(&token); let sp = token.span.substitute_dummy(def.span); let mut err = sess.parse_sess.span_diagnostic.struct_span_err(sp, &s); From ce6b7179afcdf6ae2dad7e69c56f1f5c957b47bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 21:29:36 +0000 Subject: [PATCH 170/223] Detect closures assigned to binding in block Fix #58497. --- .../rustc_borrowck/src/borrowck_errors.rs | 7 ++--- .../src/diagnostics/conflict_errors.rs | 31 ++++++++++++++++--- .../src/diagnostics/explain_borrow.rs | 12 +++++-- .../src/diagnostics/region_name.rs | 2 +- .../diagnostics/borrowck/borrowck-3.rs | 3 +- .../diagnostics/borrowck/borrowck-3.stderr | 26 +++++++++------- .../unboxed-closure-region.rs | 2 +- .../unboxed-closure-region.stderr | 27 +++++++++------- src/tools/rustfmt/tests/target/issue_4110.rs | 1 + 9 files changed, 75 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index e4942f9b666e..a4943d112042 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -440,15 +440,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { closure_kind: &str, borrowed_path: &str, capture_span: Span, + scope: &str, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, closure_span, E0373, - "{} may outlive the current function, but it borrows {}, which is owned by the current \ - function", - closure_kind, - borrowed_path, + "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \ + which is owned by the current {scope}", ); err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 492c8d020126..d99bfc01a429 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1423,6 +1423,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // // then just use the normal error. The closure isn't escaping // and `move` will not help here. + ( + Some(name), + BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _), + ) => self.report_escaping_closure_capture( + borrow_spans, + borrow_span, + &RegionName { + name: self.synthesize_region_name(), + source: RegionNameSource::Static, + }, + ConstraintCategory::CallArgument(None), + var_or_use_span, + &format!("`{}`", name), + "block", + ), ( Some(name), BorrowExplanation::MustBeValidFor { @@ -1443,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category, span, &format!("`{}`", name), + "function", ), ( name, @@ -1895,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(err) } + #[instrument(level = "debug", skip(self))] fn report_escaping_closure_capture( &mut self, use_span: UseSpans<'tcx>, @@ -1903,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category: ConstraintCategory<'tcx>, constraint_span: Span, captured_var: &str, + scope: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -1933,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None => "closure", }; - let mut err = - self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span); + let mut err = self.cannot_capture_in_long_lived_closure( + args_span, + kind, + captured_var, + var_span, + scope, + ); err.span_suggestion_verbose( sugg_span, &format!( @@ -1956,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { err.note( "async blocks are not executed immediately and must either take a \ - reference or ownership of outside variables they use", + reference or ownership of outside variables they use", ); } else { - let msg = format!("function requires argument type to outlive `{}`", fr_name); + let msg = format!("{scope} requires argument type to outlive `{fr_name}`"); err.span_note(constraint_span, &msg); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 00f5e8a83972..c4ae30151c4b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// First span returned points to the location of the conflicting use /// Second span if `Some` is returned in the case of closures and points /// to the use of the path + #[instrument(level = "debug", skip(self))] fn later_use_kind( &self, borrow: &BorrowData<'tcx>, @@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let block = &self.body.basic_blocks[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)), + kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)), .. }) = block.statements.get(location.statement_index) { - LaterUseKind::FakeLetRead + if let Some(l) = place.as_local() + && let local_decl = &self.body.local_decls[l] + && local_decl.ty.is_closure() + { + LaterUseKind::ClosureCapture + } else { + LaterUseKind::FakeLetRead + } } else if self.was_captured_by_trait_object(borrow) { LaterUseKind::TraitCapture } else if location.statement_index == block.statements.len() { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index dbd4cac7b143..579ce90a760f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// increment the counter. /// /// This is _not_ idempotent. Call `give_region_a_name` when possible. - fn synthesize_region_name(&self) -> Symbol { + pub(crate) fn synthesize_region_name(&self) -> Symbol { let c = self.next_region_name.replace_with(|counter| *counter + 1); Symbol::intern(&format!("'{:?}", c)) } diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs index bdd6cb79b60b..00f50c33e1cc 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -8,10 +8,9 @@ struct Point { fn main() { let mut c = { let mut p = Point {x: "1".to_string(), y: "2".to_string() }; - || { + || { //~ ERROR closure may outlive the current block, but it borrows `p` let x = &mut p.x; println!("{:?}", p); - //~^ ERROR `p` does not live long enough } }; c(); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr index dab1809a381e..ee9238047868 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -1,18 +1,22 @@ -error[E0597]: `p` does not live long enough - --> $DIR/borrowck-3.rs:13:29 +error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block + --> $DIR/borrowck-3.rs:11:9 | -LL | let mut c = { - | ----- borrow later stored here -LL | let mut p = Point {x: "1".to_string(), y: "2".to_string() }; LL | || { - | -- value captured here + | ^^ may outlive borrowed value `p` LL | let x = &mut p.x; LL | println!("{:?}", p); - | ^ borrowed value does not live long enough -... -LL | }; - | - `p` dropped here while still borrowed + | - `p` is borrowed here + | +note: block requires argument type to outlive `'1` + --> $DIR/borrowck-3.rs:9:9 + | +LL | let mut c = { + | ^^^^^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-region.rs index f202492eda55..51fe118c93ff 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-region.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-region.rs @@ -5,7 +5,7 @@ fn main() { let _f = { let x = 0; - || x //~ ERROR `x` does not live long enough + || x //~ ERROR closure may outlive the current block, but it borrows `x` }; _f; } diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr index b40b2f67d9ba..43e9af24a7c2 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr @@ -1,16 +1,21 @@ -error[E0597]: `x` does not live long enough - --> $DIR/unboxed-closure-region.rs:8:12 +error[E0373]: closure may outlive the current block, but it borrows `x`, which is owned by the current block + --> $DIR/unboxed-closure-region.rs:8:9 + | +LL | || x + | ^^ - `x` is borrowed here + | | + | may outlive borrowed value `x` + | +note: block requires argument type to outlive `'1` + --> $DIR/unboxed-closure-region.rs:6:9 | LL | let _f = { - | -- borrow later stored here -LL | let x = 0; -LL | || x - | -- ^ borrowed value does not live long enough - | | - | value captured here -LL | }; - | - `x` dropped here while still borrowed + | ^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | move || x + | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs index 4a58c3946e12..d3734e90b7ff 100644 --- a/src/tools/rustfmt/tests/target/issue_4110.rs +++ b/src/tools/rustfmt/tests/target/issue_4110.rs @@ -20,6 +20,7 @@ fn bindings() { category, span, &format!("`{}`", name), + "function", ), ( ref name, From 1983a627b37c98e6660dd74ea3a56ac157fc2777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2023 00:45:10 +0000 Subject: [PATCH 171/223] Detect bindings assigned blocks without tail expressions Address #44173 for type check errors. --- compiler/rustc_hir_typeck/src/demand.rs | 45 +++++++++++ ...-assigned-block-without-tail-expression.rs | 16 ++++ ...igned-block-without-tail-expression.stderr | 79 +++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 src/test/ui/type/binding-assigned-block-without-tail-expression.rs create mode 100644 src/test/ui/type/binding-assigned-block-without-tail-expression.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 9c6c53abf074..a9e6b1411700 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -75,6 +75,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_need_for_fn_pointer(err, expected, expr_ty); self.note_internal_mutation_in_method(err, expr, expected, expr_ty); self.check_for_range_as_method_call(err, expr, expr_ty, expected); + self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected); } /// Requires that the two types unify, and prints an error message if @@ -1670,4 +1671,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } + + /// Identify when the type error is because `()` is found in a binding that was assigned a + /// block without a tail expression. + fn check_for_binding_assigned_block_without_tail_expression( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'_>, + checked_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) { + if !checked_ty.is_unit() { + return; + } + let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; }; + let hir::def::Res::Local(hir_id) = path.res else { return; }; + let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else { + return; + }; + let Some(hir::Node::Local(hir::Local { + ty: None, + init: Some(init), + .. + })) = self.tcx.hir().find_parent(pat.hir_id) else { return; }; + let hir::ExprKind::Block(block, None) = init.kind else { return; }; + if block.expr.is_some() { + return; + } + let [.., stmt] = block.stmts else { + err.span_help(block.span, "this empty block is missing a tail expression"); + return; + }; + let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; }; + let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; }; + if self.can_eq(self.param_env, expected_ty, ty).is_ok() { + err.span_suggestion_verbose( + stmt.span.with_lo(tail_expr.span.hi()), + "remove this semicolon", + "", + Applicability::MachineApplicable, + ); + } else { + err.span_help(block.span, "this block is missing a tail expression"); + } + } } diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.rs b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs new file mode 100644 index 000000000000..b5b23a9e6728 --- /dev/null +++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs @@ -0,0 +1,16 @@ +fn main() { + let x = { + println!("foo"); + 42; + }; + let y = {}; + let z = { + "hi"; + }; + println!("{}", x); //~ ERROR E0277 + println!("{}", y); //~ ERROR E0277 + println!("{}", z); //~ ERROR E0277 + let _: i32 = x; //~ ERROR E0308 + let _: i32 = y; //~ ERROR E0308 + let _: i32 = z; //~ ERROR E0308 +} diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr new file mode 100644 index 000000000000..46300104b05a --- /dev/null +++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -0,0 +1,79 @@ +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:10:20 + | +LL | println!("{}", x); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:11:20 + | +LL | println!("{}", y); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:12:20 + | +LL | println!("{}", z); + | ^ `()` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:13:18 + | +LL | let _: i32 = x; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + | +help: remove this semicolon + | +LL - 42; +LL + 42 + | + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:14:18 + | +LL | let _: i32 = y; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + | +help: this empty block is missing a tail expression + --> $DIR/binding-assigned-block-without-tail-expression.rs:6:13 + | +LL | let y = {}; + | ^^ + +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:15:18 + | +LL | let _: i32 = z; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + | +help: this block is missing a tail expression + --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 + | +LL | let z = { + | _____________^ +LL | | "hi"; +LL | | }; + | |_____^ + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. From 1fa6ada9dd3a17fc8c99b6b559a2835946803d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2023 02:43:16 +0000 Subject: [PATCH 172/223] Detect bindings assigned blocks without tail expressions in trait errors Address #44173 for trait errors. --- .../src/traits/error_reporting/mod.rs | 54 +++++++++----- .../src/traits/error_reporting/suggestions.rs | 72 ++++++++++++++++++- ...-assigned-block-without-tail-expression.rs | 6 ++ ...igned-block-without-tail-expression.stderr | 68 +++++++++++++++--- 4 files changed, 172 insertions(+), 28 deletions(-) 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 6996ddd87299..714fbcf4eaa6 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -771,7 +771,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ), } }; - + self.check_for_binding_assigned_block_without_tail_expression( + &obligation, + &mut err, + trait_predicate, + ); if self.suggest_add_reference_to_arg( &obligation, &mut err, @@ -2267,23 +2271,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) = (body_id, subst.map(|subst| subst.unpack())) { - struct FindExprBySpan<'hir> { - span: Span, - result: Option<&'hir hir::Expr<'hir>>, - } - - impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> { - fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { - if self.span == ex.span { - self.result = Some(ex); - } else { - hir::intravisit::walk_expr(self, ex); - } - } - } - - let mut expr_finder = FindExprBySpan { span, result: None }; - + let mut expr_finder = FindExprBySpan::new(span); expr_finder.visit_expr(&self.tcx.hir().body(body_id).value); if let Some(hir::Expr { @@ -2770,6 +2758,36 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } +/// Crude way of getting back an `Expr` from a `Span`. +pub struct FindExprBySpan<'hir> { + pub span: Span, + pub result: Option<&'hir hir::Expr<'hir>>, + pub ty_result: Option<&'hir hir::Ty<'hir>>, +} + +impl<'hir> FindExprBySpan<'hir> { + fn new(span: Span) -> Self { + Self { span, result: None, ty_result: None } + } +} + +impl<'v> Visitor<'v> for FindExprBySpan<'v> { + fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) { + if self.span == ex.span { + self.result = Some(ex); + } else { + hir::intravisit::walk_expr(self, ex); + } + } + fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) { + if self.span == ty.span { + self.ty_result = Some(ty); + } else { + hir::intravisit::walk_ty(self, ty); + } + } +} + /// Look for type `param` in an ADT being used only through a reference to confirm that suggesting /// `param: ?Sized` would be a valid constraint. struct FindTypeParam { 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 8c2c18287749..ad2711209e25 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1,6 +1,9 @@ // ignore-tidy-filelength -use super::{DefIdOrName, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation}; +use super::{ + DefIdOrName, FindExprBySpan, Obligation, ObligationCause, ObligationCauseCode, + PredicateObligation, +}; use crate::autoderef::Autoderef; use crate::infer::InferCtxt; @@ -196,6 +199,13 @@ pub trait TypeErrCtxtExt<'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool; + fn check_for_binding_assigned_block_without_tail_expression( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ); + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, @@ -1032,6 +1042,66 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { true } + fn check_for_binding_assigned_block_without_tail_expression( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) { + let mut span = obligation.cause.span; + while span.from_expansion() { + // Remove all the desugaring and macro contexts. + span.remove_mark(); + } + let mut expr_finder = FindExprBySpan::new(span); + let Some(hir::Node::Expr(body)) = self.tcx.hir().find(obligation.cause.body_id) else { return; }; + expr_finder.visit_expr(&body); + let Some(expr) = expr_finder.result else { return; }; + let Some(typeck) = &self.typeck_results else { return; }; + let Some(ty) = typeck.expr_ty_adjusted_opt(expr) else { return; }; + if !ty.is_unit() { + return; + }; + let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind else { return; }; + let hir::def::Res::Local(hir_id) = path.res else { return; }; + let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(hir_id) else { + return; + }; + let Some(hir::Node::Local(hir::Local { + ty: None, + init: Some(init), + .. + })) = self.tcx.hir().find_parent(pat.hir_id) else { return; }; + let hir::ExprKind::Block(block, None) = init.kind else { return; }; + if block.expr.is_some() { + return; + } + let [.., stmt] = block.stmts else { + err.span_help(block.span, "this empty block is missing a tail expression"); + return; + }; + let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; }; + let Some(ty) = typeck.expr_ty_opt(tail_expr) else { + err.span_help(block.span, "this block is missing a tail expression"); + return; + }; + let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty)); + let trait_pred_and_self = trait_pred.map_bound(|trait_pred| (trait_pred, ty)); + + let new_obligation = + self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); + if self.predicate_must_hold_modulo_regions(&new_obligation) { + err.span_suggestion_verbose( + stmt.span.with_lo(tail_expr.span.hi()), + "remove this semicolon", + "", + Applicability::MachineApplicable, + ); + } else { + err.span_help(block.span, "this block is missing a tail expression"); + } + } + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.rs b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs index b5b23a9e6728..09afd27a079b 100644 --- a/src/test/ui/type/binding-assigned-block-without-tail-expression.rs +++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.rs @@ -1,3 +1,4 @@ +struct S; fn main() { let x = { println!("foo"); @@ -7,10 +8,15 @@ fn main() { let z = { "hi"; }; + let s = { + S; + }; println!("{}", x); //~ ERROR E0277 println!("{}", y); //~ ERROR E0277 println!("{}", z); //~ ERROR E0277 + println!("{}", s); //~ ERROR E0277 let _: i32 = x; //~ ERROR E0308 let _: i32 = y; //~ ERROR E0308 let _: i32 = z; //~ ERROR E0308 + let _: i32 = s; //~ ERROR E0308 } diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr index 46300104b05a..646c632517ae 100644 --- a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr +++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -1,5 +1,5 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/binding-assigned-block-without-tail-expression.rs:10:20 + --> $DIR/binding-assigned-block-without-tail-expression.rs:14:20 | LL | println!("{}", x); | ^ `()` cannot be formatted with the default formatter @@ -7,19 +7,29 @@ LL | println!("{}", x); = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove this semicolon + | +LL - 42; +LL + 42 + | error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/binding-assigned-block-without-tail-expression.rs:11:20 + --> $DIR/binding-assigned-block-without-tail-expression.rs:15:20 | LL | println!("{}", y); | ^ `()` cannot be formatted with the default formatter | +help: this empty block is missing a tail expression + --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 + | +LL | let y = {}; + | ^^ = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/binding-assigned-block-without-tail-expression.rs:12:20 + --> $DIR/binding-assigned-block-without-tail-expression.rs:16:20 | LL | println!("{}", z); | ^ `()` cannot be formatted with the default formatter @@ -27,9 +37,32 @@ LL | println!("{}", z); = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) +help: remove this semicolon + | +LL - "hi"; +LL + "hi" + | + +error[E0277]: `()` doesn't implement `std::fmt::Display` + --> $DIR/binding-assigned-block-without-tail-expression.rs:17:20 + | +LL | println!("{}", s); + | ^ `()` cannot be formatted with the default formatter + | +help: this block is missing a tail expression + --> $DIR/binding-assigned-block-without-tail-expression.rs:11:13 + | +LL | let s = { + | _____________^ +LL | | S; +LL | | }; + | |_____^ + = help: the trait `std::fmt::Display` is not implemented for `()` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types - --> $DIR/binding-assigned-block-without-tail-expression.rs:13:18 + --> $DIR/binding-assigned-block-without-tail-expression.rs:18:18 | LL | let _: i32 = x; | --- ^ expected `i32`, found `()` @@ -43,7 +76,7 @@ LL + 42 | error[E0308]: mismatched types - --> $DIR/binding-assigned-block-without-tail-expression.rs:14:18 + --> $DIR/binding-assigned-block-without-tail-expression.rs:19:18 | LL | let _: i32 = y; | --- ^ expected `i32`, found `()` @@ -51,13 +84,13 @@ LL | let _: i32 = y; | expected due to this | help: this empty block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:6:13 + --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 | LL | let y = {}; | ^^ error[E0308]: mismatched types - --> $DIR/binding-assigned-block-without-tail-expression.rs:15:18 + --> $DIR/binding-assigned-block-without-tail-expression.rs:20:18 | LL | let _: i32 = z; | --- ^ expected `i32`, found `()` @@ -65,7 +98,7 @@ LL | let _: i32 = z; | expected due to this | help: this block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 + --> $DIR/binding-assigned-block-without-tail-expression.rs:8:13 | LL | let z = { | _____________^ @@ -73,7 +106,24 @@ LL | | "hi"; LL | | }; | |_____^ -error: aborting due to 6 previous errors +error[E0308]: mismatched types + --> $DIR/binding-assigned-block-without-tail-expression.rs:21:18 + | +LL | let _: i32 = s; + | --- ^ expected `i32`, found `()` + | | + | expected due to this + | +help: this block is missing a tail expression + --> $DIR/binding-assigned-block-without-tail-expression.rs:11:13 + | +LL | let s = { + | _____________^ +LL | | S; +LL | | }; + | |_____^ + +error: aborting due to 8 previous errors Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. From a9d093bd6b88e0f129cfd9d063337940dd8823b8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 6 Jan 2023 00:28:39 +0000 Subject: [PATCH 173/223] Report WF error for new solver too --- .../rustc_trait_selection/src/traits/error_reporting/mod.rs | 4 ++-- src/test/ui/chalkify/recursive_where_clause_on_type.rs | 4 ++-- src/test/ui/chalkify/recursive_where_clause_on_type.stderr | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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 6996ddd87299..571067cc2214 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1168,7 +1168,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ty::PredicateKind::WellFormed(ty) => { - if self.tcx.sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk { + if self.tcx.sess.opts.unstable_opts.trait_solver == TraitSolver::Classic { // WF predicates cannot themselves make // errors. They can only block due to // ambiguity; otherwise, they always @@ -1180,7 +1180,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // which bounds actually failed to hold. self.tcx.sess.struct_span_err( span, - &format!("the type `{}` is not well-formed (chalk)", ty), + &format!("the type `{}` is not well-formed", ty), ) } } diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.rs b/src/test/ui/chalkify/recursive_where_clause_on_type.rs index 5855f000c7b9..c2c8aa6aabec 100644 --- a/src/test/ui/chalkify/recursive_where_clause_on_type.rs +++ b/src/test/ui/chalkify/recursive_where_clause_on_type.rs @@ -25,6 +25,6 @@ fn foo() { fn main() { // For some reason, the error is duplicated... - foo::() //~ ERROR the type `S` is not well-formed (chalk) - //~^ ERROR the type `S` is not well-formed (chalk) + foo::() //~ ERROR the type `S` is not well-formed + //~^ ERROR the type `S` is not well-formed } diff --git a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr index fddd58959278..cead5adeaaad 100644 --- a/src/test/ui/chalkify/recursive_where_clause_on_type.stderr +++ b/src/test/ui/chalkify/recursive_where_clause_on_type.stderr @@ -1,10 +1,10 @@ -error: the type `S` is not well-formed (chalk) +error: the type `S` is not well-formed --> $DIR/recursive_where_clause_on_type.rs:28:11 | LL | foo::() | ^ -error: the type `S` is not well-formed (chalk) +error: the type `S` is not well-formed --> $DIR/recursive_where_clause_on_type.rs:28:5 | LL | foo::() From 031e0854509759ccf7dbc697bfd5d958adac83f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2023 02:49:15 +0000 Subject: [PATCH 174/223] Tweak output --- compiler/rustc_hir_typeck/src/_match.rs | 6 +- compiler/rustc_hir_typeck/src/demand.rs | 6 +- .../src/traits/error_reporting/suggestions.rs | 8 +- ...igned-block-without-tail-expression.stderr | 90 ++++++++----------- 4 files changed, 44 insertions(+), 66 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index b47a5cf993b4..b6f19d3cc684 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -224,14 +224,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut ret_span: MultiSpan = semi_span.into(); ret_span.push_span_label( expr.span, - "this could be implicitly returned but it is a statement, not a \ - tail expression", + "this could be implicitly returned but it is a statement, not a tail expression", ); ret_span.push_span_label(ret, "the `match` arms can conform to this return type"); ret_span.push_span_label( semi_span, - "the `match` is a statement because of this semicolon, consider \ - removing it", + "the `match` is a statement because of this semicolon, consider removing it", ); diag.span_note(ret_span, "you might have meant to return the `match` expression"); diag.tool_only_span_suggestion( diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index a9e6b1411700..bbe15eb589da 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1699,20 +1699,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return; } let [.., stmt] = block.stmts else { - err.span_help(block.span, "this empty block is missing a tail expression"); + err.span_label(block.span, "this empty block is missing a tail expression"); return; }; let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; }; let Some(ty) = self.node_ty_opt(tail_expr.hir_id) else { return; }; if self.can_eq(self.param_env, expected_ty, ty).is_ok() { - err.span_suggestion_verbose( + err.span_suggestion_short( stmt.span.with_lo(tail_expr.span.hi()), "remove this semicolon", "", Applicability::MachineApplicable, ); } else { - err.span_help(block.span, "this block is missing a tail expression"); + err.span_label(block.span, "this block is missing a tail expression"); } } } 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 ad2711209e25..d0c2359f06f9 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1077,12 +1077,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { return; } let [.., stmt] = block.stmts else { - err.span_help(block.span, "this empty block is missing a tail expression"); + err.span_label(block.span, "this empty block is missing a tail expression"); return; }; let hir::StmtKind::Semi(tail_expr) = stmt.kind else { return; }; let Some(ty) = typeck.expr_ty_opt(tail_expr) else { - err.span_help(block.span, "this block is missing a tail expression"); + err.span_label(block.span, "this block is missing a tail expression"); return; }; let ty = self.resolve_numeric_literals_with_default(self.resolve_vars_if_possible(ty)); @@ -1091,14 +1091,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let new_obligation = self.mk_trait_obligation_with_new_self_ty(obligation.param_env, trait_pred_and_self); if self.predicate_must_hold_modulo_regions(&new_obligation) { - err.span_suggestion_verbose( + err.span_suggestion_short( stmt.span.with_lo(tail_expr.span.hi()), "remove this semicolon", "", Applicability::MachineApplicable, ); } else { - err.span_help(block.span, "this block is missing a tail expression"); + err.span_label(block.span, "this block is missing a tail expression"); } } diff --git a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr index 646c632517ae..3e96d7f317b4 100644 --- a/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr +++ b/src/test/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -1,29 +1,25 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:14:20 | +LL | 42; + | - help: remove this semicolon +... LL | println!("{}", x); | ^ `()` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: remove this semicolon - | -LL - 42; -LL + 42 - | error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:15:20 | +LL | let y = {}; + | -- this empty block is missing a tail expression +... LL | println!("{}", y); | ^ `()` cannot be formatted with the default formatter | -help: this empty block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 - | -LL | let y = {}; - | ^^ = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -31,32 +27,28 @@ LL | let y = {}; error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:16:20 | +LL | "hi"; + | - help: remove this semicolon +... LL | println!("{}", z); | ^ `()` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) -help: remove this semicolon - | -LL - "hi"; -LL + "hi" - | error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:17:20 | -LL | println!("{}", s); - | ^ `()` cannot be formatted with the default formatter - | -help: this block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:11:13 - | LL | let s = { - | _____________^ + | _____________- LL | | S; LL | | }; - | |_____^ + | |_____- this block is missing a tail expression +... +LL | println!("{}", s); + | ^ `()` cannot be formatted with the default formatter + | = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info) @@ -64,64 +56,52 @@ LL | | }; error[E0308]: mismatched types --> $DIR/binding-assigned-block-without-tail-expression.rs:18:18 | +LL | 42; + | - help: remove this semicolon +... LL | let _: i32 = x; | --- ^ expected `i32`, found `()` | | | expected due to this - | -help: remove this semicolon - | -LL - 42; -LL + 42 - | error[E0308]: mismatched types --> $DIR/binding-assigned-block-without-tail-expression.rs:19:18 | +LL | let y = {}; + | -- this empty block is missing a tail expression +... LL | let _: i32 = y; | --- ^ expected `i32`, found `()` | | | expected due to this - | -help: this empty block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:7:13 - | -LL | let y = {}; - | ^^ error[E0308]: mismatched types --> $DIR/binding-assigned-block-without-tail-expression.rs:20:18 | -LL | let _: i32 = z; - | --- ^ expected `i32`, found `()` - | | - | expected due to this - | -help: this block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:8:13 - | LL | let z = { - | _____________^ + | _____________- LL | | "hi"; LL | | }; - | |_____^ + | |_____- this block is missing a tail expression +... +LL | let _: i32 = z; + | --- ^ expected `i32`, found `()` + | | + | expected due to this error[E0308]: mismatched types --> $DIR/binding-assigned-block-without-tail-expression.rs:21:18 | -LL | let _: i32 = s; - | --- ^ expected `i32`, found `()` - | | - | expected due to this - | -help: this block is missing a tail expression - --> $DIR/binding-assigned-block-without-tail-expression.rs:11:13 - | LL | let s = { - | _____________^ + | _____________- LL | | S; LL | | }; - | |_____^ + | |_____- this block is missing a tail expression +... +LL | let _: i32 = s; + | --- ^ expected `i32`, found `()` + | | + | expected due to this error: aborting due to 8 previous errors From 523fe7a121e80b5959bfa6203268a46e9d9e7dd4 Mon Sep 17 00:00:00 2001 From: yanchen4791 Date: Fri, 16 Dec 2022 14:47:24 -0800 Subject: [PATCH 175/223] Suggests adding named lifetime when the return contains value borrowed from more than one lifetimes of the function's inputs --- .../src/diagnostics/region_errors.rs | 13 +++- .../src/infer/error_reporting/mod.rs | 1 + .../nice_region_error/static_impl_trait.rs | 77 +++++++++++++++++-- .../static-return-lifetime-infered.rs | 2 - .../static-return-lifetime-infered.stderr | 32 +------- src/test/ui/lifetimes/issue-105227.fixed | 26 +++++++ src/test/ui/lifetimes/issue-105227.rs | 26 +++++++ src/test/ui/lifetimes/issue-105227.stderr | 47 +++++++++++ 8 files changed, 184 insertions(+), 40 deletions(-) create mode 100644 src/test/ui/lifetimes/issue-105227.fixed create mode 100644 src/test/ui/lifetimes/issue-105227.rs create mode 100644 src/test/ui/lifetimes/issue-105227.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 567a9814fccb..cc33ef14756e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -192,6 +192,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // buffered in the `MirBorrowckCtxt`. let mut outlives_suggestion = OutlivesSuggestionBuilder::default(); + let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> = + None; for nll_error in nll_errors.into_iter() { match nll_error { @@ -234,13 +236,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty); let named_key = self.regioncx.name_regions(self.infcx.tcx, key); let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); - self.buffer_error(unexpected_hidden_region_diagnostic( + let mut diag = unexpected_hidden_region_diagnostic( self.infcx.tcx, span, named_ty, named_region, named_key, - )); + ); + if last_unexpected_hidden_region != Some((span, named_ty, named_key)) { + self.buffer_error(diag); + last_unexpected_hidden_region = Some((span, named_ty, named_key)); + } else { + diag.delay_as_bug(); + } } RegionErrorKind::BoundUniversalRegionError { @@ -730,6 +738,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(arg), captures, Some((param.param_ty_span, param.param_ty.to_string())), + self.infcx.tcx.is_suitable_region(f).map(|r| r.def_id), ); } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7222eb776820..0644c7ada10f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -303,6 +303,7 @@ pub fn unexpected_hidden_region_diagnostic<'tcx>( None, format!("captures `{}`", hidden_region), None, + Some(reg_info.def_id), ) } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index d9cdfa9dd4fc..94662780c36e 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -8,13 +8,17 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; -use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; +use rustc_hir::{ + self as hir, GenericBound, GenericParamKind, Item, ItemKind, Lifetime, LifetimeName, Node, + TyKind, +}; use rustc_middle::ty::{ self, AssocItemContainer, StaticLifetimeVisitor, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, }; use rustc_span::symbol::Ident; use rustc_span::Span; +use rustc_span::def_id::LocalDefId; use std::ops::ControlFlow; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { @@ -268,6 +272,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(arg), captures, Some((param.param_ty_span, param.param_ty.to_string())), + Some(anon_reg_sup.def_id), ); let reported = err.emit(); @@ -283,6 +288,7 @@ pub fn suggest_new_region_bound( arg: Option, captures: String, param: Option<(Span, String)>, + scope_def_id: Option, ) { debug!("try_report_static_impl_trait: fn_return={:?}", fn_returns); // FIXME: account for the need of parens in `&(dyn Trait + '_)` @@ -340,12 +346,69 @@ pub fn suggest_new_region_bound( _ => false, }) { } else { - err.span_suggestion_verbose( - fn_return.span.shrink_to_hi(), - &format!("{declare} `{ty}` {captures}, {explicit}",), - &plus_lt, - Applicability::MaybeIncorrect, - ); + // get a lifetime name of existing named lifetimes if any + let existing_lt_name = if let Some(id) = scope_def_id + && let Some(generics) = tcx.hir().get_generics(id) + && let named_lifetimes = generics + .params + .iter() + .filter(|p| matches!(p.kind, GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Explicit })) + .map(|p| { if let hir::ParamName::Plain(name) = p.name {Some(name.to_string())} else {None}}) + .filter(|n| ! matches!(n, None)) + .collect::>() + && named_lifetimes.len() > 0 { + named_lifetimes[0].clone() + } else { + None + }; + let name = if let Some(name) = &existing_lt_name { + format!("{}", name) + } else { + format!("'a") + }; + // if there are more than one elided lifetimes in inputs, the explicit `'_` lifetime cannot be used. + // introducing a new lifetime `'a` or making use of one from existing named lifetimes if any + if let Some(id) = scope_def_id + && let Some(generics) = tcx.hir().get_generics(id) + && let mut spans_suggs = generics + .params + .iter() + .filter(|p| p.is_elided_lifetime()) + .map(|p| + if p.span.hi() - p.span.lo() == rustc_span::BytePos(1) { // Ampersand (elided without '_) + (p.span.shrink_to_hi(),format!("{name} ")) + } else { // Underscore (elided with '_) + (p.span, format!("{name}")) + } + ) + .collect::>() + && spans_suggs.len() > 1 + { + let use_lt = + if existing_lt_name == None { + spans_suggs.push((generics.span.shrink_to_hi(), format!("<{name}>"))); + format!("you can introduce a named lifetime parameter `{name}`") + } else { + // make use the existing named lifetime + format!("you can use the named lifetime parameter `{name}`") + }; + spans_suggs + .push((fn_return.span.shrink_to_hi(), format!(" + {name} "))); + err.multipart_suggestion_verbose( + &format!( + "{declare} `{ty}` {captures}, {use_lt}", + ), + spans_suggs, + Applicability::MaybeIncorrect, + ); + } else { + err.span_suggestion_verbose( + fn_return.span.shrink_to_hi(), + &format!("{declare} `{ty}` {captures}, {explicit}",), + &plus_lt, + Applicability::MaybeIncorrect, + ); + } } } TyKind::TraitObject(_, lt, _) => { diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.rs b/src/test/ui/impl-trait/static-return-lifetime-infered.rs index f940c1949d0b..36ef9ea44434 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.rs +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.rs @@ -6,12 +6,10 @@ impl A { fn iter_values_anon(&self) -> impl Iterator { self.x.iter().map(|a| a.0) //~^ ERROR: captures lifetime that does not appear in bounds - //~| ERROR: captures lifetime that does not appear in bounds } fn iter_values<'a>(&'a self) -> impl Iterator { self.x.iter().map(|a| a.0) //~^ ERROR: captures lifetime that does not appear in bounds - //~| ERROR: captures lifetime that does not appear in bounds } } diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index b365bd884548..c451f8e37c4e 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -12,23 +12,10 @@ LL | fn iter_values_anon(&self) -> impl Iterator + '_ { | ++++ error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:7:9 - | -LL | fn iter_values_anon(&self) -> impl Iterator { - | ----- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:7:27: 7:30]>` captures the anonymous lifetime defined here -LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: to declare that `impl Iterator` captures `'_`, you can add an explicit `'_` lifetime bound - | -LL | fn iter_values_anon(&self) -> impl Iterator + '_ { - | ++++ - -error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:12:9 + --> $DIR/static-return-lifetime-infered.rs:11:9 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here + | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:11:27: 11:30]>` captures the lifetime `'a` as defined here LL | self.x.iter().map(|a| a.0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -37,19 +24,6 @@ help: to declare that `impl Iterator` captures `'a`, you can add an LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ++++ -error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds - --> $DIR/static-return-lifetime-infered.rs:12:9 - | -LL | fn iter_values<'a>(&'a self) -> impl Iterator { - | -- hidden type `Map, [closure@$DIR/static-return-lifetime-infered.rs:12:27: 12:30]>` captures the lifetime `'a` as defined here -LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: to declare that `impl Iterator` captures `'a`, you can add an explicit `'a` lifetime bound - | -LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { - | ++++ - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/lifetimes/issue-105227.fixed b/src/test/ui/lifetimes/issue-105227.fixed new file mode 100644 index 000000000000..f6ed9c82e915 --- /dev/null +++ b/src/test/ui/lifetimes/issue-105227.fixed @@ -0,0 +1,26 @@ +// Regression test for issue #105227. + +// run-rustfix +#![allow(warnings)] +fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v.0.chars().chain(v.1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds +} + +fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v0.chars().chain(v1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> +//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + (impl Iterator + 'b , &'b str) +{ + (v0.chars().chain(v1.chars()), v2) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn main() { +} diff --git a/src/test/ui/lifetimes/issue-105227.rs b/src/test/ui/lifetimes/issue-105227.rs new file mode 100644 index 000000000000..6427a50bb87e --- /dev/null +++ b/src/test/ui/lifetimes/issue-105227.rs @@ -0,0 +1,26 @@ +// Regression test for issue #105227. + +// run-rustfix +#![allow(warnings)] +fn chars0(v :(& str, &str)) -> impl Iterator { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v.0.chars().chain(v.1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bounds +} + +fn chars1(v0 : & str, v1 : &str) -> impl Iterator { +//~^ HELP to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + v0.chars().chain(v1.chars()) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> +//~^ HELP to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + (impl Iterator, &'b str) +{ + (v0.chars().chain(v1.chars()), v2) + //~^ ERROR hidden type for `impl Iterator` captures lifetime that does not appear in bound +} + +fn main() { +} diff --git a/src/test/ui/lifetimes/issue-105227.stderr b/src/test/ui/lifetimes/issue-105227.stderr new file mode 100644 index 000000000000..d21145937357 --- /dev/null +++ b/src/test/ui/lifetimes/issue-105227.stderr @@ -0,0 +1,47 @@ +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:7:5 + | +LL | fn chars0(v :(& str, &str)) -> impl Iterator { + | ----- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +LL | +LL | v.0.chars().chain(v.1.chars()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + | +LL | fn chars0<'a>(v :(&'a str, &'a str)) -> impl Iterator + 'a { + | ++++ ++ ++ ++++ + +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:13:5 + | +LL | fn chars1(v0 : & str, v1 : &str) -> impl Iterator { + | ----- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +LL | +LL | v0.chars().chain(v1.chars()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can introduce a named lifetime parameter `'a` + | +LL | fn chars1<'a>(v0 : &'a str, v1 : &'a str) -> impl Iterator + 'a { + | ++++ ++ ++ ++++ + +error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds + --> $DIR/issue-105227.rs:21:5 + | +LL | fn chars2<'b>(v0 : &str, v1 : &'_ str, v2 : &'b str) -> + | ---- hidden type `std::iter::Chain, Chars<'_>>` captures the anonymous lifetime defined here +... +LL | (v0.chars().chain(v1.chars()), v2) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: to declare that `impl Iterator` captures `'_`, you can use the named lifetime parameter `'b` + | +LL ~ fn chars2<'b>(v0 : &'b str, v1 : &'b str, v2 : &'b str) -> +LL | +LL ~ (impl Iterator + 'b , &'b str) + | + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0700`. From 10dbcf063033eb842a80ff386e268f8448ccf1ed Mon Sep 17 00:00:00 2001 From: Yiming Lei Date: Thu, 5 Jan 2023 09:12:37 -0800 Subject: [PATCH 176/223] fix [type error] for error E0029 and E0277 check explicitly for the type references error if ty.references_error() is true change the error to be err.delay_as_bug() and prevent the error E0029 and E0277 from emitting out this fix #105946 --- compiler/rustc_hir_typeck/src/pat.rs | 3 ++ .../src/traits/error_reporting/mod.rs | 1 - .../src/traits/error_reporting/suggestions.rs | 14 ++++-- src/test/ui/typeck/issue-105946.rs | 12 +++++ src/test/ui/typeck/issue-105946.stderr | 49 +++++++++++++++++++ 5 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/typeck/issue-105946.rs create mode 100644 src/test/ui/typeck/issue-105946.stderr diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 28e959b7c6a1..1dff671b8c6b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -553,6 +553,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs), _ => span_bug!(span, "Impossible, verified above."), } + if (lhs, rhs).references_error() { + err.downgrade_to_delayed_bug(); + } if self.tcx.sess.teach(&err.get_code().unwrap()) { err.note( "In a match expression, only numbers and characters can be matched \ 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 8a08c7533aa1..8ec14526d153 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1387,7 +1387,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { self.note_obligation_cause(&mut err, &obligation); self.point_at_returns_when_relevant(&mut err, &obligation); - err.emit(); } } 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 7c21a1047bcb..83e3486540a5 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -248,7 +248,7 @@ pub trait TypeErrCtxtExt<'tcx> { fn point_at_returns_when_relevant( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, obligation: &PredicateObligation<'tcx>, ); @@ -1686,7 +1686,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { fn point_at_returns_when_relevant( &self, - err: &mut Diagnostic, + err: &mut DiagnosticBuilder<'tcx, ErrorGuaranteed>, obligation: &PredicateObligation<'tcx>, ) { match obligation.cause.code().peel_derives() { @@ -1708,7 +1708,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for expr in &visitor.returns { if let Some(returned_ty) = typeck_results.node_type_opt(expr.hir_id) { let ty = self.resolve_vars_if_possible(returned_ty); - err.span_label(expr.span, &format!("this returned value is of type `{}`", ty)); + if ty.references_error() { + // don't print out the [type error] here + err.delay_as_bug(); + } else { + err.span_label( + expr.span, + &format!("this returned value is of type `{}`", ty), + ); + } } } } diff --git a/src/test/ui/typeck/issue-105946.rs b/src/test/ui/typeck/issue-105946.rs new file mode 100644 index 000000000000..bf01751d5f6e --- /dev/null +++ b/src/test/ui/typeck/issue-105946.rs @@ -0,0 +1,12 @@ +fn digit() -> str { + return {}; + //~^ ERROR: mismatched types [E0308] +} +fn main() { + let [_y..] = [box 1, box 2]; + //~^ ERROR: cannot find value `_y` in this scope [E0425] + //~| ERROR: `X..` patterns in slices are experimental [E0658] + //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658] + //~| ERROR: box expression syntax is experimental; you can call `Box::new` instead [E0658] + //~| ERROR: pattern requires 1 element but array has 2 [E0527] +} diff --git a/src/test/ui/typeck/issue-105946.stderr b/src/test/ui/typeck/issue-105946.stderr new file mode 100644 index 000000000000..d803de4df472 --- /dev/null +++ b/src/test/ui/typeck/issue-105946.stderr @@ -0,0 +1,49 @@ +error[E0425]: cannot find value `_y` in this scope + --> $DIR/issue-105946.rs:6:10 + | +LL | let [_y..] = [box 1, box 2]; + | ^^ not found in this scope + +error[E0658]: `X..` patterns in slices are experimental + --> $DIR/issue-105946.rs:6:10 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^ + | + = note: see issue #67264 for more information + = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable + +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/issue-105946.rs:6:19 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error[E0658]: box expression syntax is experimental; you can call `Box::new` instead + --> $DIR/issue-105946.rs:6:26 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^ + | + = note: see issue #49733 for more information + = help: add `#![feature(box_syntax)]` to the crate attributes to enable + +error[E0308]: mismatched types + --> $DIR/issue-105946.rs:2:10 + | +LL | return {}; + | ^^ expected `str`, found `()` + +error[E0527]: pattern requires 1 element but array has 2 + --> $DIR/issue-105946.rs:6:9 + | +LL | let [_y..] = [box 1, box 2]; + | ^^^^^^ expected 2 elements + +error: aborting due to 6 previous errors + +Some errors have detailed explanations: E0308, E0425, E0527, E0658. +For more information about an error, try `rustc --explain E0308`. From 0edca66a905d4c9c7292a2f89421a07389c8ade6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2023 05:34:56 +0000 Subject: [PATCH 177/223] Tiny formatting fix --- compiler/rustc_parse/src/parser/expr.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1fc1ffd6cb6e..9f436783ceda 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1503,12 +1503,13 @@ impl<'a> Parser<'a> { prior_type_ascription: self.last_type_ascription, }); (lo.to(self.prev_token.span), ExprKind::MacCall(mac)) - } else if self.check(&token::OpenDelim(Delimiter::Brace)) && - let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) { - if qself.is_some() { - self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); - } - return expr; + } else if self.check(&token::OpenDelim(Delimiter::Brace)) + && let Some(expr) = self.maybe_parse_struct_expr(&qself, &path) + { + if qself.is_some() { + self.sess.gated_spans.gate(sym::more_qualified_paths, path.span); + } + return expr; } else { (path.span, ExprKind::Path(qself, path)) }; From ae667be0f6017002587a28be257238655d34fa54 Mon Sep 17 00:00:00 2001 From: Gijs Burghoorn Date: Fri, 6 Jan 2023 13:20:58 +0100 Subject: [PATCH 178/223] Remove HTML tags around warning --- library/core/src/macros/mod.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index be13317008c0..3b026bc0e0f3 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1315,9 +1315,6 @@ pub(crate) mod builtin { /// Parses a file as an expression or an item according to the context. /// - ///
- ///
-    ///
     /// **Warning**: For multi-file Rust projects, the `include!` macro is probably not what you
     /// are looking for. Usually, multi-file Rust projects use
     /// [modules](https://doc.rust-lang.org/reference/items/modules.html). Multi-file projects and
@@ -1326,9 +1323,6 @@ pub(crate) mod builtin {
     /// explained in the Rust Book
     /// [here](https://doc.rust-lang.org/book/ch07-02-defining-modules-to-control-scope-and-privacy.html).
     ///
-    /// 
- ///
- /// /// The included file is placed in the surrounding code /// [unhygienically](https://doc.rust-lang.org/reference/macros-by-example.html#hygiene). If /// the included file is parsed as an expression and variables or functions share names across From 804dea9ca6a02baedb1efc639b848fa080dbf51d Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Fri, 6 Jan 2023 20:55:10 +0900 Subject: [PATCH 179/223] use smaller spans for missing lifetime/generic args fix rustdoc ui test --- .../wrong_number_of_generic_args.rs | 20 ++++++--- src/test/rustdoc-ui/issue-105742.stderr | 44 +++++++++---------- src/test/ui/consts/issue-103790.stderr | 2 +- .../elided-in-expr-position.stderr | 4 +- .../gat-trait-path-missing-lifetime.stderr | 4 +- .../issue-71176.stderr | 2 +- .../issue-76535.base.stderr | 2 +- .../issue-76535.extended.stderr | 2 +- .../issue-78671.base.stderr | 2 +- .../issue-78671.extended.stderr | 2 +- .../issue-79422.base.stderr | 2 +- .../issue-79422.extended.stderr | 2 +- .../issue-79636-1.stderr | 2 +- .../issue-79636-2.stderr | 2 +- .../issue-80433.stderr | 2 +- .../issue-81712-cyclic-traits.stderr | 2 +- .../issue-81862.stderr | 2 +- .../missing_lifetime_args.stderr | 2 +- ...eric-type-less-params-with-defaults.stderr | 2 +- .../ui/generics/wrong-number-of-args.stderr | 12 ++--- .../ui/impl-trait/issues/issue-92305.stderr | 2 +- src/test/ui/issues/issue-14092.stderr | 2 +- src/test/ui/issues/issue-23024.stderr | 2 +- src/test/ui/issues/issue-86756.stderr | 2 +- .../missing-lifetime-in-alias.stderr | 2 +- src/test/ui/tag-type-args.stderr | 2 +- .../ui/type/ascription/issue-34255-1.stderr | 2 +- .../ui/ufcs/ufcs-qpath-missing-params.stderr | 4 +- 28 files changed, 70 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs index 3df8f776eded..574b1e8b485a 100644 --- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs @@ -597,11 +597,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let span = self.path_segment.ident.span; // insert a suggestion of the form "Y<'a, 'b>" - let ident = self.path_segment.ident.name.to_ident_string(); - let sugg = format!("{}<{}>", ident, suggested_args); + let sugg = format!("<{}>", suggested_args); debug!("sugg: {:?}", sugg); - err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders); + err.span_suggestion_verbose( + span.shrink_to_hi(), + &msg, + sugg, + Applicability::HasPlaceholders, + ); } AngleBrackets::Available => { @@ -643,11 +647,15 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let span = self.path_segment.ident.span; // insert a suggestion of the form "Y" - let ident = self.path_segment.ident.name.to_ident_string(); - let sugg = format!("{}<{}>", ident, suggested_args); + let sugg = format!("<{}>", suggested_args); debug!("sugg: {:?}", sugg); - err.span_suggestion_verbose(span, &msg, sugg, Applicability::HasPlaceholders); + err.span_suggestion_verbose( + span.shrink_to_hi(), + &msg, + sugg, + Applicability::HasPlaceholders, + ); } AngleBrackets::Available => { let gen_args_span = self.gen_args.span().unwrap(); diff --git a/src/test/rustdoc-ui/issue-105742.stderr b/src/test/rustdoc-ui/issue-105742.stderr index cc101b7ff375..ffb602cf8619 100644 --- a/src/test/rustdoc-ui/issue-105742.stderr +++ b/src/test/rustdoc-ui/issue-105742.stderr @@ -12,7 +12,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | ::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:13:21 @@ -28,7 +28,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | ::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:18:37 @@ -44,7 +44,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:18:37 @@ -60,7 +60,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:30 @@ -76,7 +76,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item<'a>> as SVec>::Item, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:30 @@ -92,7 +92,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:46 @@ -108,7 +108,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item> as SVec>::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:46 @@ -124,7 +124,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:5:40 @@ -140,7 +140,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | pub fn next<'a, T>(s: &'a mut dyn SVec = T, Output = T>) { - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:5:40 @@ -156,7 +156,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | pub fn next<'a, T>(s: &'a mut dyn SVec = T, Output = T>) { - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:13:21 @@ -172,7 +172,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | ::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:13:21 @@ -188,7 +188,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | ::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:18:37 @@ -204,7 +204,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:18:37 @@ -220,7 +220,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:30 @@ -236,7 +236,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item<'a>> as SVec>::Item, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:30 @@ -252,7 +252,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:46 @@ -268,7 +268,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | Output = ::Item> as SVec>::Item<'a>, - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:23:46 @@ -284,7 +284,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | Output = ::Item> as SVec>::Item, - | ~~~~~~~ + | +++ error[E0038]: the trait `SVec` cannot be made into an object --> $DIR/issue-105742.rs:5:31 @@ -329,7 +329,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | fn len(&self) -> ::Item<'_>; - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:35:38 @@ -345,7 +345,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | fn len(&self) -> ::Item; - | ~~~~~~~ + | +++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:35:38 @@ -361,7 +361,7 @@ LL | type Item<'a, T>; help: add missing lifetime argument | LL | fn len(&self) -> ::Item<'_>; - | ~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `SVec::Item` --> $DIR/issue-105742.rs:35:38 @@ -377,7 +377,7 @@ LL | type Item<'a, T>; help: add missing generic argument | LL | fn len(&self) -> ::Item; - | ~~~~~~~ + | +++ error: aborting due to 23 previous errors diff --git a/src/test/ui/consts/issue-103790.stderr b/src/test/ui/consts/issue-103790.stderr index 41b0816dc32a..34d8ee281cf8 100644 --- a/src/test/ui/consts/issue-103790.stderr +++ b/src/test/ui/consts/issue-103790.stderr @@ -20,7 +20,7 @@ LL | struct S; help: add missing generic argument | LL | struct S = { S }>; - | ~~~~ + | +++ error[E0391]: cycle detected when computing type of `S::S` --> $DIR/issue-103790.rs:4:32 diff --git a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr index a9996123f234..842b23bd49dd 100644 --- a/src/test/ui/generic-associated-types/elided-in-expr-position.stderr +++ b/src/test/ui/generic-associated-types/elided-in-expr-position.stderr @@ -12,7 +12,7 @@ LL | type Assoc<'a> where Self: 'a; help: add missing lifetime argument | LL | fn g(&self) -> Self::Assoc<'_>; - | ~~~~~~~~~ + | ++++ error[E0107]: missing generics for associated type `Trait::Assoc` --> $DIR/elided-in-expr-position.rs:31:26 @@ -28,7 +28,7 @@ LL | type Assoc<'a> where Self: 'a; help: add missing lifetime argument | LL | fn g(&self) -> Self::Assoc<'_> { - | ~~~~~~~~~ + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr index 452dfefd1e3d..499221637ba7 100644 --- a/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr +++ b/src/test/ui/generic-associated-types/gat-trait-path-missing-lifetime.stderr @@ -12,7 +12,7 @@ LL | type Y<'a>; help: add missing lifetime argument | LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { - | ~~~~~ + | ++++ error[E0107]: missing generics for associated type `X::Y` --> $DIR/gat-trait-path-missing-lifetime.rs:8:20 @@ -28,7 +28,7 @@ LL | type Y<'a>; help: add missing lifetime argument | LL | fn foo<'a, T1: X = T1>>(t : T1) -> T1::Y<'a> { - | ~~~~~ + | ++++ error: aborting due to 2 previous errors diff --git a/src/test/ui/generic-associated-types/issue-71176.stderr b/src/test/ui/generic-associated-types/issue-71176.stderr index 386c97161c8f..4b4fe43e8c4f 100644 --- a/src/test/ui/generic-associated-types/issue-71176.stderr +++ b/src/test/ui/generic-associated-types/issue-71176.stderr @@ -12,7 +12,7 @@ LL | type A<'a>; help: add missing lifetime argument | LL | inner: Box = B>>, - | ~~~~~ + | ++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-76535.base.stderr b/src/test/ui/generic-associated-types/issue-76535.base.stderr index 088f69b09f70..52c6e3eec603 100644 --- a/src/test/ui/generic-associated-types/issue-76535.base.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.base.stderr @@ -12,7 +12,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; help: add missing lifetime argument | LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); - | ~~~~~~~~~~~ + | ++++ error[E0038]: the trait `SuperTrait` cannot be made into an object --> $DIR/issue-76535.rs:39:14 diff --git a/src/test/ui/generic-associated-types/issue-76535.extended.stderr b/src/test/ui/generic-associated-types/issue-76535.extended.stderr index e79f0a73f5b5..369b86d29284 100644 --- a/src/test/ui/generic-associated-types/issue-76535.extended.stderr +++ b/src/test/ui/generic-associated-types/issue-76535.extended.stderr @@ -12,7 +12,7 @@ LL | type SubType<'a>: SubTrait where Self: 'a; help: add missing lifetime argument | LL | let sub: Box = SubStruct>> = Box::new(SuperStruct::new(0)); - | ~~~~~~~~~~~ + | ++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-78671.base.stderr b/src/test/ui/generic-associated-types/issue-78671.base.stderr index 514f8d45a15f..bad8c1c9dba7 100644 --- a/src/test/ui/generic-associated-types/issue-78671.base.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.base.stderr @@ -12,7 +12,7 @@ LL | type Member; help: add missing generic argument | LL | Box::new(Family) as &dyn CollectionFamily=usize> - | ~~~~~~~~~ + | +++ error[E0038]: the trait `CollectionFamily` cannot be made into an object --> $DIR/issue-78671.rs:10:25 diff --git a/src/test/ui/generic-associated-types/issue-78671.extended.stderr b/src/test/ui/generic-associated-types/issue-78671.extended.stderr index 6fa09a4c7e59..1d8a3d410f8d 100644 --- a/src/test/ui/generic-associated-types/issue-78671.extended.stderr +++ b/src/test/ui/generic-associated-types/issue-78671.extended.stderr @@ -12,7 +12,7 @@ LL | type Member; help: add missing generic argument | LL | Box::new(Family) as &dyn CollectionFamily=usize> - | ~~~~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-79422.base.stderr b/src/test/ui/generic-associated-types/issue-79422.base.stderr index 3c1a29d48b2f..f1de77bc3c0a 100644 --- a/src/test/ui/generic-associated-types/issue-79422.base.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.base.stderr @@ -12,7 +12,7 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; help: add missing lifetime argument | LL | as Box = dyn RefCont<'_, u8>>>; - | ~~~~~~~~~~~~ + | ++++ error[E0038]: the trait `MapLike` cannot be made into an object --> $DIR/issue-79422.rs:47:12 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 58c921bf09f6..d79de0ca6279 100644 --- a/src/test/ui/generic-associated-types/issue-79422.extended.stderr +++ b/src/test/ui/generic-associated-types/issue-79422.extended.stderr @@ -12,7 +12,7 @@ LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a; help: add missing lifetime argument | LL | as Box = dyn RefCont<'_, u8>>>; - | ~~~~~~~~~~~~ + | ++++ error[E0271]: type mismatch resolving ` as MapLike>::VRefCont<'_> == (dyn RefCont<'_, u8> + 'static)` --> $DIR/issue-79422.rs:44:13 diff --git a/src/test/ui/generic-associated-types/issue-79636-1.stderr b/src/test/ui/generic-associated-types/issue-79636-1.stderr index 155477048cad..6e0d2ff4ded4 100644 --- a/src/test/ui/generic-associated-types/issue-79636-1.stderr +++ b/src/test/ui/generic-associated-types/issue-79636-1.stderr @@ -12,7 +12,7 @@ LL | type Wrapped; help: add missing generic argument | LL | MInner: Monad = MOuter::Wrapped>, - | ~~~~~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-79636-2.stderr b/src/test/ui/generic-associated-types/issue-79636-2.stderr index 6a36bfc37f24..16287323995d 100644 --- a/src/test/ui/generic-associated-types/issue-79636-2.stderr +++ b/src/test/ui/generic-associated-types/issue-79636-2.stderr @@ -12,7 +12,7 @@ LL | type Wrapped: SomeTrait; help: add missing generic argument | LL | W: SomeTrait = W>, - | ~~~~~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-80433.stderr b/src/test/ui/generic-associated-types/issue-80433.stderr index 20a407dd4125..4f4f96a4b921 100644 --- a/src/test/ui/generic-associated-types/issue-80433.stderr +++ b/src/test/ui/generic-associated-types/issue-80433.stderr @@ -12,7 +12,7 @@ LL | type Output<'a>; help: add missing lifetime argument | LL | fn test_simpler<'a>(dst: &'a mut impl TestMut = &'a mut f32>) - | ~~~~~~~~~~ + | ++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr index c8961e28ede4..e0fc225f463a 100644 --- a/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr +++ b/src/test/ui/generic-associated-types/issue-81712-cyclic-traits.stderr @@ -12,7 +12,7 @@ LL | type DType: D; help: add missing generic argument | LL | type CType: C = Self>; - | ~~~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/issue-81862.stderr b/src/test/ui/generic-associated-types/issue-81862.stderr index 9e21c567c73c..df30be65ec54 100644 --- a/src/test/ui/generic-associated-types/issue-81862.stderr +++ b/src/test/ui/generic-associated-types/issue-81862.stderr @@ -12,7 +12,7 @@ LL | type Item<'a>; help: add missing lifetime argument | LL | fn next(&mut self) -> Option>; - | ~~~~~~~~ + | ++++ error: aborting due to previous error diff --git a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr index 752587c25a73..8f74b12c008e 100644 --- a/src/test/ui/generic-associated-types/missing_lifetime_args.stderr +++ b/src/test/ui/generic-associated-types/missing_lifetime_args.stderr @@ -12,7 +12,7 @@ LL | type Y<'a, 'b>; help: add missing lifetime arguments | LL | fn foo<'c, 'd>(_arg: Box = (&'c u32, &'d u32)>>) {} - | ~~~~~~~~~ + | ++++++++ error[E0107]: this struct takes 3 lifetime arguments but 2 lifetime arguments were supplied --> $DIR/missing_lifetime_args.rs:14:26 diff --git a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr index e45a0d9ca773..6450bbd8b432 100644 --- a/src/test/ui/generics/generic-type-less-params-with-defaults.stderr +++ b/src/test/ui/generics/generic-type-less-params-with-defaults.stderr @@ -12,7 +12,7 @@ LL | struct Vec( help: add missing generic argument | LL | let _: Vec; - | ~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/generics/wrong-number-of-args.stderr b/src/test/ui/generics/wrong-number-of-args.stderr index b48966a1a1ed..75e33f680ead 100644 --- a/src/test/ui/generics/wrong-number-of-args.stderr +++ b/src/test/ui/generics/wrong-number-of-args.stderr @@ -251,7 +251,7 @@ LL | struct Ty; help: add missing generic arguments | LL | type A = Ty; - | ~~~~~~~~ + | ++++++ error[E0107]: this struct takes 2 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:30:14 @@ -315,7 +315,7 @@ LL | struct Ty<'a, T>; help: add missing generic argument | LL | type A = Ty; - | ~~~~~ + | +++ error[E0107]: this struct takes 1 generic argument but 0 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:54:14 @@ -391,7 +391,7 @@ LL | struct Ty; help: add missing generic arguments | LL | type A = Ty; - | ~~~~~~~~ + | ++++++ error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:84:14 @@ -483,7 +483,7 @@ LL | trait GenericType { help: add missing generic argument | LL | type D = Box>; - | ~~~~~~~~~~~~~~ + | +++ error[E0107]: this trait takes 1 generic argument but 2 generic arguments were supplied --> $DIR/wrong-number-of-args.rs:133:22 @@ -892,7 +892,7 @@ LL | type A = HashMap; help: add missing generic arguments | LL | type A = HashMap; - | ~~~~~~~~~~~~~ + | ++++++ error[E0107]: this struct takes at least 2 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:314:18 @@ -954,7 +954,7 @@ LL | type A = Result; help: add missing generic arguments | LL | type A = Result; - | ~~~~~~~~~~~~ + | ++++++ error[E0107]: this enum takes 2 generic arguments but 1 generic argument was supplied --> $DIR/wrong-number-of-args.rs:338:18 diff --git a/src/test/ui/impl-trait/issues/issue-92305.stderr b/src/test/ui/impl-trait/issues/issue-92305.stderr index f09c14d3df1d..86d7184da7a4 100644 --- a/src/test/ui/impl-trait/issues/issue-92305.stderr +++ b/src/test/ui/impl-trait/issues/issue-92305.stderr @@ -7,7 +7,7 @@ LL | fn f(data: &[T]) -> impl Iterator { help: add missing generic argument | LL | fn f(data: &[T]) -> impl Iterator> { - | ~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-14092.stderr b/src/test/ui/issues/issue-14092.stderr index 132e2b101a5f..3a43627e6910 100644 --- a/src/test/ui/issues/issue-14092.stderr +++ b/src/test/ui/issues/issue-14092.stderr @@ -7,7 +7,7 @@ LL | fn fn1(0: Box) {} help: add missing generic argument | LL | fn fn1(0: Box) {} - | ~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-23024.stderr b/src/test/ui/issues/issue-23024.stderr index 014eb2897b48..2c325ffcceea 100644 --- a/src/test/ui/issues/issue-23024.stderr +++ b/src/test/ui/issues/issue-23024.stderr @@ -16,7 +16,7 @@ LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); help: add missing generic argument | LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); - | ~~~~~~~~ + | ++++++ error[E0191]: the value of the associated type `Output` (from trait `FnOnce`) must be specified --> $DIR/issue-23024.rs:8:39 diff --git a/src/test/ui/issues/issue-86756.stderr b/src/test/ui/issues/issue-86756.stderr index 693cfecedc4b..6c5917bdf6ec 100644 --- a/src/test/ui/issues/issue-86756.stderr +++ b/src/test/ui/issues/issue-86756.stderr @@ -42,7 +42,7 @@ LL | trait Foo {} help: add missing generic argument | LL | eq::> - | ~~~~~~ + | +++ error: aborting due to 3 previous errors; 1 warning emitted diff --git a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr index 428b8f14b6fc..20159e144072 100644 --- a/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr +++ b/src/test/ui/lifetimes/missing-lifetime-in-alias.stderr @@ -39,7 +39,7 @@ LL | type Bar<'b> help: add missing lifetime argument | LL | type C<'a, 'b> = as Trait>::Bar<'a>; - | ~~~~~~~ + | ++++ error: aborting due to 3 previous errors diff --git a/src/test/ui/tag-type-args.stderr b/src/test/ui/tag-type-args.stderr index 107af76413d3..5b54880a6855 100644 --- a/src/test/ui/tag-type-args.stderr +++ b/src/test/ui/tag-type-args.stderr @@ -12,7 +12,7 @@ LL | enum Quux { Bar } help: add missing generic argument | LL | fn foo(c: Quux) { assert!((false)); } - | ~~~~~~~ + | +++ error: aborting due to previous error diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr index fd43e1114c89..fafff19f8f6e 100644 --- a/src/test/ui/type/ascription/issue-34255-1.stderr +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -28,7 +28,7 @@ LL | input_cells: Vec::new() help: add missing generic argument | LL | input_cells: Vec::new() - | ~~~~~~ + | +++ error: aborting due to 3 previous errors diff --git a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr index a832964d220a..d0ec47d61321 100644 --- a/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr +++ b/src/test/ui/ufcs/ufcs-qpath-missing-params.stderr @@ -12,7 +12,7 @@ LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { help: add missing generic argument | LL | >::into_cow("foo".to_string()); - | ~~~~~~~~~~ + | +++ error[E0107]: missing generics for trait `IntoCow` --> $DIR/ufcs-qpath-missing-params.rs:17:16 @@ -28,7 +28,7 @@ LL | pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { help: add missing generic argument | LL | >::into_cow::("foo".to_string()); - | ~~~~~~~~~~ + | +++ error[E0107]: this associated function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/ufcs-qpath-missing-params.rs:17:26 From f67aa04114f348c07f8a83cfa1b126aebbe8c636 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Jan 2023 15:18:36 +0100 Subject: [PATCH 180/223] Update browser-ui-test version --- .../docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version index 475434e5aef8..c39e9c5fbc9d 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/browser-ui-test.version @@ -1 +1 @@ -0.13.4 \ No newline at end of file +0.14.1 \ No newline at end of file From 4a68f7ecae0bc69915b33018aac4df199dba9885 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 4 Jan 2023 20:56:46 +0000 Subject: [PATCH 181/223] Correctly render sidebar for relative module paths --- src/librustdoc/html/render/context.rs | 22 +++++-- src/librustdoc/html/render/write_shared.rs | 74 ++++++++++++++-------- src/librustdoc/html/sources.rs | 60 +++++++++++++----- 3 files changed, 109 insertions(+), 47 deletions(-) diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index d4d3e4f6ea79..c8899ee62b5f 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -309,7 +309,7 @@ impl<'tcx> Context<'tcx> { pub(crate) fn href_from_span(&self, span: clean::Span, with_lines: bool) -> Option { let mut root = self.root_path(); - let mut path = String::new(); + let mut path: String; let cnum = span.cnum(self.sess()); // We can safely ignore synthetic `SourceFile`s. @@ -340,10 +340,24 @@ impl<'tcx> Context<'tcx> { ExternalLocation::Unknown => return None, }; - sources::clean_path(&src_root, file, false, |component| { - path.push_str(&component.to_string_lossy()); + let href = RefCell::new(PathBuf::new()); + sources::clean_path( + &src_root, + file, + |component| { + href.borrow_mut().push(component); + }, + || { + href.borrow_mut().pop(); + }, + ); + + path = href.into_inner().to_string_lossy().to_string(); + + if let Some(c) = path.as_bytes().last() && *c != b'/' { path.push('/'); - }); + } + let mut fname = file.file_name().expect("source has no filename").to_os_string(); fname.push(".html"); path.push_str(&fname.to_string_lossy()); diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index eaf149a43005..3ea4c4bea882 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -1,8 +1,9 @@ +use std::cell::RefCell; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Component, Path}; -use std::rc::Rc; +use std::rc::{Rc, Weak}; use itertools::Itertools; use rustc_data_structures::flock; @@ -184,23 +185,26 @@ pub(super) fn write_shared( use std::ffi::OsString; - #[derive(Debug)] + #[derive(Debug, Default)] struct Hierarchy { + parent: Weak, elem: OsString, - children: FxHashMap, - elems: FxHashSet, + children: RefCell>>, + elems: RefCell>, } impl Hierarchy { - fn new(elem: OsString) -> Hierarchy { - Hierarchy { elem, children: FxHashMap::default(), elems: FxHashSet::default() } + fn with_parent(elem: OsString, parent: &Rc) -> Self { + Self { elem, parent: Rc::downgrade(parent), ..Self::default() } } fn to_json_string(&self) -> String { - let mut subs: Vec<&Hierarchy> = self.children.values().collect(); + let borrow = self.children.borrow(); + let mut subs: Vec<_> = borrow.values().collect(); subs.sort_unstable_by(|a, b| a.elem.cmp(&b.elem)); let mut files = self .elems + .borrow() .iter() .map(|s| format!("\"{}\"", s.to_str().expect("invalid osstring conversion"))) .collect::>(); @@ -220,36 +224,52 @@ pub(super) fn write_shared( files = files ) } + + fn add_path(self: &Rc, path: &Path) { + let mut h = Rc::clone(&self); + let mut elems = path + .components() + .filter_map(|s| match s { + Component::Normal(s) => Some(s.to_owned()), + Component::ParentDir => Some(OsString::from("..")), + _ => None, + }) + .peekable(); + loop { + let cur_elem = elems.next().expect("empty file path"); + if cur_elem == ".." { + if let Some(parent) = h.parent.upgrade() { + h = parent; + } + continue; + } + if elems.peek().is_none() { + h.elems.borrow_mut().insert(cur_elem); + break; + } else { + let entry = Rc::clone( + h.children + .borrow_mut() + .entry(cur_elem.clone()) + .or_insert_with(|| Rc::new(Self::with_parent(cur_elem, &h))), + ); + h = entry; + } + } + } } if cx.include_sources { - let mut hierarchy = Hierarchy::new(OsString::new()); + let hierarchy = Rc::new(Hierarchy::default()); for source in cx .shared .local_sources .iter() .filter_map(|p| p.0.strip_prefix(&cx.shared.src_root).ok()) { - let mut h = &mut hierarchy; - let mut elems = source - .components() - .filter_map(|s| match s { - Component::Normal(s) => Some(s.to_owned()), - _ => None, - }) - .peekable(); - loop { - let cur_elem = elems.next().expect("empty file path"); - if elems.peek().is_none() { - h.elems.insert(cur_elem); - break; - } else { - let e = cur_elem.clone(); - h = h.children.entry(cur_elem.clone()).or_insert_with(|| Hierarchy::new(e)); - } - } + hierarchy.add_path(source); } - + let hierarchy = Rc::try_unwrap(hierarchy).unwrap(); let dst = cx.dst.join(&format!("source-files{}.js", cx.shared.resource_suffix)); let make_sources = || { let (mut all_sources, _krates) = diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index e639fadeb967..799c497d1370 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -13,6 +13,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::source_map::FileName; +use std::cell::RefCell; use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; @@ -72,12 +73,22 @@ impl LocalSourcesCollector<'_, '_> { return; } - let mut href = String::new(); - clean_path(self.src_root, &p, false, |component| { - href.push_str(&component.to_string_lossy()); - href.push('/'); - }); + let href = RefCell::new(PathBuf::new()); + clean_path( + &self.src_root, + &p, + |component| { + href.borrow_mut().push(component); + }, + || { + href.borrow_mut().pop(); + }, + ); + let mut href = href.into_inner().to_string_lossy().to_string(); + if let Some(c) = href.as_bytes().last() && *c != b'/' { + href.push('/'); + } let mut src_fname = p.file_name().expect("source has no filename").to_os_string(); src_fname.push(".html"); href.push_str(&src_fname.to_string_lossy()); @@ -180,13 +191,28 @@ impl SourceCollector<'_, '_> { let shared = Rc::clone(&self.cx.shared); // Create the intermediate directories - let mut cur = self.dst.clone(); - let mut root_path = String::from("../../"); - clean_path(&shared.src_root, &p, false, |component| { - cur.push(component); - root_path.push_str("../"); - }); + let cur = RefCell::new(PathBuf::new()); + let root_path = RefCell::new(PathBuf::new()); + clean_path( + &shared.src_root, + &p, + |component| { + cur.borrow_mut().push(component); + root_path.borrow_mut().push(".."); + }, + || { + cur.borrow_mut().pop(); + root_path.borrow_mut().pop(); + }, + ); + + let root_path = PathBuf::from("../../").join(root_path.into_inner()); + let mut root_path = root_path.to_string_lossy(); + if let Some(c) = root_path.as_bytes().last() && *c != b'/' { + root_path += "/"; + } + let mut cur = self.dst.join(cur.into_inner()); shared.ensure_dir(&cur)?; let src_fname = p.file_name().expect("source has no filename").to_os_string(); @@ -232,11 +258,13 @@ impl SourceCollector<'_, '_> { /// Takes a path to a source file and cleans the path to it. This canonicalizes /// things like ".." to components which preserve the "top down" hierarchy of a /// static HTML tree. Each component in the cleaned path will be passed as an -/// argument to `f`. The very last component of the path (ie the file name) will -/// be passed to `f` if `keep_filename` is true, and ignored otherwise. -pub(crate) fn clean_path(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) +/// argument to `f`. The very last component of the path (ie the file name) is ignored. +/// If a `..` is encountered, the `parent` closure will be called to allow the callee to +/// handle it. +pub(crate) fn clean_path(src_root: &Path, p: &Path, mut f: F, mut parent: P) where F: FnMut(&OsStr), + P: FnMut(), { // make it relative, if possible let p = p.strip_prefix(src_root).unwrap_or(p); @@ -244,12 +272,12 @@ where let mut iter = p.components().peekable(); while let Some(c) = iter.next() { - if !keep_filename && iter.peek().is_none() { + if iter.peek().is_none() { break; } match c { - Component::ParentDir => f("up".as_ref()), + Component::ParentDir => parent(), Component::Normal(c) => f(c), _ => continue, } From d5d1c5716747ded8ca9746be71e70cceeaa9f422 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 5 Jan 2023 04:17:57 +0000 Subject: [PATCH 182/223] Update tests --- src/test/rustdoc/src-links.rs | 5 +++++ src/test/rustdoc/src-links/fizz.rs | 1 + 2 files changed, 6 insertions(+) create mode 100644 src/test/rustdoc/src-links/fizz.rs diff --git a/src/test/rustdoc/src-links.rs b/src/test/rustdoc/src-links.rs index 353ce10243e0..7a6c733d464c 100644 --- a/src/test/rustdoc/src-links.rs +++ b/src/test/rustdoc/src-links.rs @@ -7,6 +7,11 @@ #[path = "src-links/mod.rs"] pub mod qux; +// @has src/foo/src-links.rs.html +// @has foo/fizz/index.html '//a/@href' '../src/foo/src-links/fizz.rs.html' +#[path = "src-links/../src-links/fizz.rs"] +pub mod fizz; + // @has foo/bar/index.html '//a/@href' '../../src/foo/src-links.rs.html' pub mod bar { diff --git a/src/test/rustdoc/src-links/fizz.rs b/src/test/rustdoc/src-links/fizz.rs new file mode 100644 index 000000000000..d2b76b1cec85 --- /dev/null +++ b/src/test/rustdoc/src-links/fizz.rs @@ -0,0 +1 @@ +pub struct Buzz; From 009064f8902d89e71230af8188a3241d97477d37 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Jan 2023 15:18:51 +0100 Subject: [PATCH 183/223] Use new block syntax for define-function in goml scripts --- src/test/rustdoc-gui/anchors.goml | 80 ++++++++-------- src/test/rustdoc-gui/code-color.goml | 12 +-- src/test/rustdoc-gui/codeblock-tooltip.goml | 86 +++++++++--------- .../docblock-code-block-line-number.goml | 16 ++-- src/test/rustdoc-gui/docblock-table.goml | 32 +++---- src/test/rustdoc-gui/headers-color.goml | 40 ++++---- src/test/rustdoc-gui/headings.goml | 46 +++++----- src/test/rustdoc-gui/help-page.goml | 12 +-- src/test/rustdoc-gui/highlight-colors.goml | 36 ++++---- src/test/rustdoc-gui/item-decl-colors.goml | 31 ++++--- .../rustdoc-gui/jump-to-def-background.goml | 12 +-- src/test/rustdoc-gui/links-color.goml | 36 ++++---- src/test/rustdoc-gui/notable-trait.goml | 32 +++---- src/test/rustdoc-gui/run-on-hover.goml | 22 ++--- src/test/rustdoc-gui/rust-logo.goml | 30 +++--- .../rustdoc-gui/scrape-examples-color.goml | 30 +++--- .../rustdoc-gui/scrape-examples-toggle.goml | 24 ++--- src/test/rustdoc-gui/search-no-result.goml | 20 ++-- src/test/rustdoc-gui/search-result-color.goml | 91 +++++++------------ .../rustdoc-gui/search-result-display.goml | 22 ++--- src/test/rustdoc-gui/search-tab.goml | 30 +++--- src/test/rustdoc-gui/sidebar-links-color.goml | 78 ++++++++-------- src/test/rustdoc-gui/sidebar-mobile.goml | 14 +-- .../sidebar-source-code-display.goml | 84 ++++++++--------- src/test/rustdoc-gui/sidebar-source-code.goml | 54 +++++------ src/test/rustdoc-gui/sidebar.goml | 54 +++++------ src/test/rustdoc-gui/source-code-page.goml | 40 ++++---- src/test/rustdoc-gui/stab-badge.goml | 58 ++++++------ src/test/rustdoc-gui/target.goml | 12 +-- src/test/rustdoc-gui/toggle-docs.goml | 20 ++-- src/test/rustdoc-gui/unsafe-fn.goml | 10 +- 31 files changed, 573 insertions(+), 591 deletions(-) diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml index fb8e288fae88..c9b53a1a0f76 100644 --- a/src/test/rustdoc-gui/anchors.goml +++ b/src/test/rustdoc-gui/anchors.goml @@ -3,70 +3,72 @@ define-function: ( "check-colors", (theme, main_color, title_color, fqn_color, fqn_type_color, src_link_color, sidebar_link_color), - [ - ("goto", "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html"), + block { + goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" // This is needed to ensure that the text color is computed. - ("show-text", true), + show-text: true // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("#toggle-all-docs", {"color": |main_color|})), - ("assert-css", (".fqn a:nth-of-type(1)", {"color": |fqn_color|})), - ("assert-css", (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|})), - ("assert-css", ( + assert-css: ("#toggle-all-docs", {"color": |main_color|}) + assert-css: (".fqn a:nth-of-type(1)", {"color": |fqn_color|}) + assert-css: (".fqn a:nth-of-type(2)", {"color": |fqn_type_color|}) + assert-css: ( ".rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, ALL, - )), - ( - "compare-elements-css", - (".rightside .srclink", ".rightside.srclink", ["color", "text-decoration"]), - ), - ( - "compare-elements-css", - (".main-heading .srclink", ".rightside.srclink", ["color", "text-decoration"]), - ), + ) + compare-elements-css: ( + ".rightside .srclink", + ".rightside.srclink", + ["color", "text-decoration"], + ) + compare-elements-css: ( + ".main-heading .srclink", + ".rightside.srclink", + ["color", "text-decoration"], + ) - ("move-cursor-to", ".main-heading .srclink"), - ("assert-css", ( + move-cursor-to: ".main-heading .srclink" + assert-css: ( ".main-heading .srclink", {"color": |src_link_color|, "text-decoration": "underline solid " + |src_link_color|}, - )), - ("move-cursor-to", ".impl-items .rightside .srclink"), - ("assert-css", ( + ) + move-cursor-to: ".impl-items .rightside .srclink" + assert-css: ( ".impl-items .rightside .srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, - )), - ("move-cursor-to", ".impl-items .rightside.srclink"), - ("assert-css", ( + ) + move-cursor-to: ".impl-items .rightside.srclink" + assert-css: ( ".impl-items .rightside.srclink", {"color": |src_link_color|, "text-decoration": "none solid " + |src_link_color|}, - )), + ) - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"), + goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" // Since we changed page, we need to set the theme again. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("#top-doc-prose-title", {"color": |title_color|})), + assert-css: ("#top-doc-prose-title", {"color": |title_color|}) - ("assert-css", (".sidebar a", {"color": |sidebar_link_color|})), - ("assert-css", ("h1.fqn a", {"color": |title_color|})), + assert-css: (".sidebar a", {"color": |sidebar_link_color|}) + assert-css: ("h1.fqn a", {"color": |title_color|}) // We move the cursor over the "Implementations" title so the anchor is displayed. - ("move-cursor-to", "h2#implementations"), - ("assert-css", ("h2#implementations a.anchor", {"color": |main_color|})), + move-cursor-to: "h2#implementations" + assert-css: ("h2#implementations a.anchor", {"color": |main_color|}) // Same thing with the impl block title. - ("move-cursor-to", "#impl-HeavilyDocumentedStruct"), - ("assert-css", ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|})), + move-cursor-to: "#impl-HeavilyDocumentedStruct" + assert-css: ("#impl-HeavilyDocumentedStruct a.anchor", {"color": |main_color|}) - ("assert-css", ("#title-for-struct-impl-item-doc", {"margin-left": "0px"})), - ], + assert-css: ("#title-for-struct-impl-item-doc", {"margin-left": "0px"}) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/code-color.goml b/src/test/rustdoc-gui/code-color.goml index 118f04ad6dcb..cb550a4573a6 100644 --- a/src/test/rustdoc-gui/code-color.goml +++ b/src/test/rustdoc-gui/code-color.goml @@ -9,14 +9,14 @@ show-text: true define-function: ( "check-colors", (theme, doc_code_color, doc_inline_code_color), - [ + block { // Set the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", (".docblock pre > code", {"color": |doc_code_color|}, ALL)), - ("assert-css", (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL)), - ], + reload: + assert-css: (".docblock pre > code", {"color": |doc_code_color|}, ALL) + assert-css: (".docblock > p > code", {"color": |doc_inline_code_color|}, ALL) + }, ) call-function: ("check-colors", ("ayu", "rgb(230, 225, 207)", "rgb(255, 180, 84)")) diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml index d4443f821d2a..a3ef4e77b542 100644 --- a/src/test/rustdoc-gui/codeblock-tooltip.goml +++ b/src/test/rustdoc-gui/codeblock-tooltip.goml @@ -5,32 +5,32 @@ show-text: true define-function: ( "check-colors", (theme, background, color, border), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // compile_fail block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip", {"color": "rgba(255, 0, 0, 0.5)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.compile_fail .tooltip"), + move-cursor-to: ".docblock .example-wrap.compile_fail .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip", {"color": "rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip::after", { "content": '"This example deliberately fails to compile"', @@ -39,37 +39,37 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.compile_fail .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), + ) // should_panic block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.should_panic .tooltip", {"color": "rgba(255, 0, 0, 0.5)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic", {"border-left": "2px solid rgba(255, 0, 0, 0.5)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.should_panic .tooltip"), + move-cursor-to: ".docblock .example-wrap.should_panic .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.should_panic .tooltip", {"color": "rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic .tooltip::after", { "content": '"This example panics"', @@ -78,37 +78,37 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.should_panic .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), + ) // ignore block - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.ignore .tooltip", {"color": "rgba(255, 142, 0, 0.6)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore", {"border-left": "2px solid rgba(255, 142, 0, 0.6)"}, - )), + ) - ("move-cursor-to", ".docblock .example-wrap.ignore .tooltip"), + move-cursor-to: ".docblock .example-wrap.ignore .tooltip" - ("assert-css", ( + assert-css: ( ".docblock .example-wrap.ignore .tooltip", {"color": "rgb(255, 142, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"}, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore .tooltip::after", { "content": '"This example is not tested"', @@ -117,16 +117,16 @@ define-function: ( "color": |color|, "border": "1px solid " + |border|, }, - )), - ("assert-css", ( + ) + assert-css: ( ".docblock .example-wrap.ignore .tooltip::before", { "border-width": "5px", "border-style": "solid", "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", }, - )), - ], + ) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/docblock-code-block-line-number.goml b/src/test/rustdoc-gui/docblock-code-block-line-number.goml index a3ed008719c0..69bcf5339ef2 100644 --- a/src/test/rustdoc-gui/docblock-code-block-line-number.goml +++ b/src/test/rustdoc-gui/docblock-code-block-line-number.goml @@ -11,19 +11,19 @@ assert-false: "pre.example-line-numbers" define-function: ( "check-colors", (theme, color), - [ + block { // We now set the setting to show the line numbers on code examples. - ("local-storage", { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", "rustdoc-line-numbers": "true" - }), + } // We reload to make the line numbers appear and change theme. - ("reload"), + reload: // We wait for them to be added into the DOM by the JS... - ("wait-for", "pre.example-line-numbers"), + wait-for: "pre.example-line-numbers" // If the test didn't fail, it means that it was found! - ("assert-css", ( + assert-css: ( "pre.example-line-numbers", { "color": |color|, @@ -32,8 +32,8 @@ define-function: ( "text-align": "right", }, ALL, - )), - ], + ) + }, ) call-function: ("check-colors", { "theme": "ayu", diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml index 6f9209e0ab4a..3dcb8abd4159 100644 --- a/src/test/rustdoc-gui/docblock-table.goml +++ b/src/test/rustdoc-gui/docblock-table.goml @@ -7,32 +7,32 @@ compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock tab define-function: ( "check-colors", (theme, border_color, zebra_stripe_color), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("reload"), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", { + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + reload: + assert-css: (".top-doc .docblock table tbody tr:nth-child(1)", { "background-color": "rgba(0, 0, 0, 0)", - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(2)", { "background-color": |zebra_stripe_color|, - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(3)", { "background-color": "rgba(0, 0, 0, 0)", - })), - ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", { + }) + assert-css: (".top-doc .docblock table tbody tr:nth-child(4)", { "background-color": |zebra_stripe_color|, - })), - ("assert-css", (".top-doc .docblock table td", { + }) + assert-css: (".top-doc .docblock table td", { "border-style": "solid", "border-width": "1px", "border-color": |border_color|, - })), - ("assert-css", (".top-doc .docblock table th", { + }) + assert-css: (".top-doc .docblock table th", { "border-style": "solid", "border-width": "1px", "border-color": |border_color|, - })), - ] + }) + } ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/headers-color.goml b/src/test/rustdoc-gui/headers-color.goml index c80a49c52f03..92cf050a514f 100644 --- a/src/test/rustdoc-gui/headers-color.goml +++ b/src/test/rustdoc-gui/headers-color.goml @@ -3,39 +3,39 @@ define-function: ( "check-colors", (theme, color, code_header_color, focus_background_color, headings_color), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html" // This is needed so that the text color is computed. - ("show-text", true), - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + show-text: true + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".impl", {"color": |color|, "background-color": "rgba(0, 0, 0, 0)"}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".impl .code-header", {"color": |code_header_color|, "background-color": "rgba(0, 0, 0, 0)"}, ALL, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo"), - ("assert-css", ( + ) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#impl-Foo" + assert-css: ( "#impl-Foo", {"color": |color|, "background-color": |focus_background_color|}, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use"), - ("assert-css", ( + ) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html#method.must_use" + assert-css: ( "#method\.must_use", {"color": |color|, "background-color": |focus_background_color|}, ALL, - )), - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), - ("assert-css", (".small-section-header a", {"color": |color|}, ALL)), - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html"), + ) + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" + assert-css: (".small-section-header a", {"color": |color|}, ALL) + goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" // We select headings (h2, h3, h...). - ("assert-css", (".docblock > :not(p) > a", {"color": |headings_color|}, ALL)), - ], + assert-css: (".docblock > :not(p) > a", {"color": |headings_color|}, ALL) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml index 85e17ca9551a..45b3fee26e41 100644 --- a/src/test/rustdoc-gui/headings.goml +++ b/src/test/rustdoc-gui/headings.goml @@ -157,38 +157,38 @@ goto: "file://" + |DOC_PATH| + "/test_docs/struct.HeavilyDocumentedStruct.html" define-function: ( "check-colors", (theme, heading_color, small_heading_color, heading_border_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".top-doc .docblock h2", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h3", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h4", {"color": |heading_color|, "border-bottom": "1px solid " + |heading_border_color|}, - )), - ("assert-css", ( + ) + assert-css: ( ".top-doc .docblock h5", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h4", {"color": |heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h5", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ("assert-css", ( + ) + assert-css: ( "#implementations-list .docblock h6", {"color": |small_heading_color|, "border-bottom-width": "0px"}, - )), - ], + ) + }, ) call-function: ( "check-colors", @@ -221,11 +221,11 @@ call-function: ( define-function: ( "check-since-color", (theme), - [ - ("local-storage", {"rustdoc-theme": |theme|}), - ("reload"), - ("assert-css", (".since", {"color": "rgb(128, 128, 128)"}, ALL)), - ], + block { + local-storage: {"rustdoc-theme": |theme|} + reload: + assert-css: (".since", {"color": "rgb(128, 128, 128)"}, ALL) + }, ) goto: "file://" + |DOC_PATH| + "/staged_api/struct.Foo.html" diff --git a/src/test/rustdoc-gui/help-page.goml b/src/test/rustdoc-gui/help-page.goml index 62cc9ac64972..5f4c1ba2f853 100644 --- a/src/test/rustdoc-gui/help-page.goml +++ b/src/test/rustdoc-gui/help-page.goml @@ -18,17 +18,17 @@ show-text: true define-function: ( "check-colors", (theme, color, background, box_shadow), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", ("#help kbd", { + reload: + assert-css: ("#help kbd", { "color": |color|, "background-color": |background|, "box-shadow": |box_shadow| + " 0px -1px 0px 0px inset", - }, ALL)), - ], + }, ALL) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/highlight-colors.goml b/src/test/rustdoc-gui/highlight-colors.goml index ff1be389dcb0..b182150a577d 100644 --- a/src/test/rustdoc-gui/highlight-colors.goml +++ b/src/test/rustdoc-gui/highlight-colors.goml @@ -21,24 +21,24 @@ define-function: ( comment, doc_comment, ), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ("pre.rust .kw", {"color": |kw|}, ALL)), - ("assert-css", ("pre.rust .kw-2", {"color": |kw2|}, ALL)), - ("assert-css", ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL)), - ("assert-css", ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL)), - ("assert-css", ("pre.rust .lifetime", {"color": |lifetime|}, ALL)), - ("assert-css", ("pre.rust .number", {"color": |number|}, ALL)), - ("assert-css", ("pre.rust .string", {"color": |string|}, ALL)), - ("assert-css", ("pre.rust .bool-val", {"color": |bool_val|}, ALL)), - ("assert-css", ("pre.rust .self", {"color": |self|}, ALL)), - ("assert-css", ("pre.rust .attr", {"color": |attr|}, ALL)), - ("assert-css", ("pre.rust .macro", {"color": |macro|}, ALL)), - ("assert-css", ("pre.rust .question-mark", {"color": |question_mark|}, ALL)), - ("assert-css", ("pre.rust .comment", {"color": |comment|}, ALL)), - ("assert-css", ("pre.rust .doccomment", {"color": |doc_comment|}, ALL)), - ], + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ("pre.rust .kw", {"color": |kw|}, ALL) + assert-css: ("pre.rust .kw-2", {"color": |kw2|}, ALL) + assert-css: ("pre.rust .prelude-ty", {"color": |prelude_ty|}, ALL) + assert-css: ("pre.rust .prelude-val", {"color": |prelude_val|}, ALL) + assert-css: ("pre.rust .lifetime", {"color": |lifetime|}, ALL) + assert-css: ("pre.rust .number", {"color": |number|}, ALL) + assert-css: ("pre.rust .string", {"color": |string|}, ALL) + assert-css: ("pre.rust .bool-val", {"color": |bool_val|}, ALL) + assert-css: ("pre.rust .self", {"color": |self|}, ALL) + assert-css: ("pre.rust .attr", {"color": |attr|}, ALL) + assert-css: ("pre.rust .macro", {"color": |macro|}, ALL) + assert-css: ("pre.rust .question-mark", {"color": |question_mark|}, ALL) + assert-css: ("pre.rust .comment", {"color": |comment|}, ALL) + assert-css: ("pre.rust .doccomment", {"color": |doc_comment|}, ALL) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/item-decl-colors.goml b/src/test/rustdoc-gui/item-decl-colors.goml index 2e07f19b13d6..c58e3eb7c237 100644 --- a/src/test/rustdoc-gui/item-decl-colors.goml +++ b/src/test/rustdoc-gui/item-decl-colors.goml @@ -17,22 +17,23 @@ define-function: ( fn_color, assoc_type_color, ), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html"), - ("show-text", true), - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".item-decl .code-attribute", {"color": |attr_color|}, ALL)), - ("assert-css", (".item-decl .trait", {"color": |trait_color|}, ALL)), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.WithGenerics.html" + show-text: true + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".item-decl .code-attribute", {"color": |attr_color|}, ALL) + assert-css: (".item-decl .trait", {"color": |trait_color|}, ALL) // We need to add `code` here because otherwise it would select the parent too. - ("assert-css", (".item-decl code .struct", {"color": |struct_color|}, ALL)), - ("assert-css", (".item-decl .enum", {"color": |enum_color|}, ALL)), - ("assert-css", (".item-decl .primitive", {"color": |primitive_color|}, ALL)), - ("goto", "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html"), - ("assert-css", (".item-decl .constant", {"color": |constant_color|}, ALL)), - ("assert-css", (".item-decl .fn", {"color": |fn_color|}, ALL)), - ("assert-css", (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL)), - ], + assert-css: (".item-decl code .struct", {"color": |struct_color|}, ALL) + assert-css: (".item-decl .enum", {"color": |enum_color|}, ALL) + assert-css: (".item-decl .primitive", {"color": |primitive_color|}, ALL) + + goto: "file://" + |DOC_PATH| + "/test_docs/trait.TraitWithoutGenerics.html" + assert-css: (".item-decl .constant", {"color": |constant_color|}, ALL) + assert-css: (".item-decl .fn", {"color": |fn_color|}, ALL) + assert-css: (".item-decl .associatedtype", {"color": |assoc_type_color|}, ALL) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/jump-to-def-background.goml b/src/test/rustdoc-gui/jump-to-def-background.goml index b65faf13d0c5..8ee3ccf4a211 100644 --- a/src/test/rustdoc-gui/jump-to-def-background.goml +++ b/src/test/rustdoc-gui/jump-to-def-background.goml @@ -4,17 +4,17 @@ goto: "file://" + |DOC_PATH| + "/src/link_to_definition/lib.rs.html" define-function: ( "check-background-color", (theme, background_color), - [ + block { // Set the theme. - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }), + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", ( + reload: + assert-css: ( "body.source .example-wrap pre.rust a", {"background-color": |background_color|}, ALL, - )), - ], + ) + }, ) call-function: ("check-background-color", ("ayu", "rgb(51, 51, 51)")) diff --git a/src/test/rustdoc-gui/links-color.goml b/src/test/rustdoc-gui/links-color.goml index 9402c09eb69e..14f7d99351a6 100644 --- a/src/test/rustdoc-gui/links-color.goml +++ b/src/test/rustdoc-gui/links-color.goml @@ -8,29 +8,29 @@ define-function: ( "check-colors", (theme, mod, macro, struct, enum, trait, fn, type, union, keyword, sidebar, sidebar_current, sidebar_current_background), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".item-table .mod", {"color": |mod|}, ALL)), - ("assert-css", (".item-table .macro", {"color": |macro|}, ALL)), - ("assert-css", (".item-table .struct", {"color": |struct|}, ALL)), - ("assert-css", (".item-table .enum", {"color": |enum|}, ALL)), - ("assert-css", (".item-table .trait", {"color": |trait|}, ALL)), - ("assert-css", (".item-table .fn", {"color": |fn|}, ALL)), - ("assert-css", (".item-table .type", {"color": |type|}, ALL)), - ("assert-css", (".item-table .union", {"color": |union|}, ALL)), - ("assert-css", (".item-table .keyword", {"color": |keyword|}, ALL)), + assert-css: (".item-table .mod", {"color": |mod|}, ALL) + assert-css: (".item-table .macro", {"color": |macro|}, ALL) + assert-css: (".item-table .struct", {"color": |struct|}, ALL) + assert-css: (".item-table .enum", {"color": |enum|}, ALL) + assert-css: (".item-table .trait", {"color": |trait|}, ALL) + assert-css: (".item-table .fn", {"color": |fn|}, ALL) + assert-css: (".item-table .type", {"color": |type|}, ALL) + assert-css: (".item-table .union", {"color": |union|}, ALL) + assert-css: (".item-table .keyword", {"color": |keyword|}, ALL) // Checking sidebar elements. - ("assert-css", ( + assert-css: ( ".sidebar-elems a:not(.current)", {"color": |sidebar|, "background-color": "rgba(0, 0, 0, 0)", "font-weight": "400"}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".sidebar-elems a.current", { "color": |sidebar_current|, @@ -38,8 +38,8 @@ define-function: ( "font-weight": "500", }, ALL, - )), - ], + ) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/notable-trait.goml b/src/test/rustdoc-gui/notable-trait.goml index 7d4bd27d42d4..b4fa7d0dbf0e 100644 --- a/src/test/rustdoc-gui/notable-trait.goml +++ b/src/test/rustdoc-gui/notable-trait.goml @@ -123,40 +123,40 @@ assert-count: ("//*[@class='notable popover']", 0) define-function: ( "check-colors", (theme, header_color, content_color, type_color, trait_color), - [ - ("goto", "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"), + block { + goto: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html" // This is needed to ensure that the text color is computed. - ("show-text", true), + show-text: true // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("move-cursor-to", "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']"), - ("assert-count", (".notable.popover", 1)), + move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='notable-traits']" + assert-count: (".notable.popover", 1) - ("assert-css", ( + assert-css: ( ".notable.popover h3", {"color": |header_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre", {"color": |content_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre a.struct", {"color": |type_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".notable.popover pre a.trait", {"color": |trait_color|}, ALL, - )), - ] + ) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/run-on-hover.goml b/src/test/rustdoc-gui/run-on-hover.goml index 57d63049f28c..8dcb62c10aaa 100644 --- a/src/test/rustdoc-gui/run-on-hover.goml +++ b/src/test/rustdoc-gui/run-on-hover.goml @@ -8,27 +8,27 @@ show-text: true define-function: ( "check-run-button", (theme, color, background, hover_color, hover_background), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".test-arrow", {"visibility": "hidden"})), - ("move-cursor-to", ".example-wrap"), - ("assert-css", (".test-arrow", { + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".test-arrow", {"visibility": "hidden"}) + move-cursor-to: ".example-wrap" + assert-css: (".test-arrow", { "visibility": "visible", "color": |color|, "background-color": |background|, "font-size": "22px", "border-radius": "5px", - })), - ("move-cursor-to", ".test-arrow"), - ("assert-css", (".test-arrow:hover", { + }) + move-cursor-to: ".test-arrow" + assert-css: (".test-arrow:hover", { "visibility": "visible", "color": |hover_color|, "background-color": |hover_background|, "font-size": "22px", "border-radius": "5px", - })), - ], + }) + }, ) call-function: ("check-run-button", { diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml index 816cc9abd693..e94dc9a964dd 100644 --- a/src/test/rustdoc-gui/rust-logo.goml +++ b/src/test/rustdoc-gui/rust-logo.goml @@ -4,29 +4,29 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" define-function: ( "check-logo", (theme, filter), - [ + block { // Going to the doc page. - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" // Changing theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".rust-logo", {"filter": |filter|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".rust-logo", {"filter": |filter|}) // Going to the source code page. - ("goto", "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html"), + goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" // Changing theme (since it's local files, the local storage works by folder). - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", (".rust-logo", {"filter": |filter|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: (".rust-logo", {"filter": |filter|}) // Now we check that the non-rust logos don't have a CSS filter set. - ("goto", "file://" + |DOC_PATH| + "/huge_logo/index.html"), + goto: "file://" + |DOC_PATH| + "/huge_logo/index.html" // Changing theme on the new page (again...). - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // Check there is no rust logo - ("assert-false", ".rust-logo"), + assert-false: ".rust-logo" // Check there is no filter. - ("assert-css", (".sidebar .logo-container img", {"filter": "none"})), - ], + assert-css: (".sidebar .logo-container img", {"filter": "none"}) + }, ) call-function: ( diff --git a/src/test/rustdoc-gui/scrape-examples-color.goml b/src/test/rustdoc-gui/scrape-examples-color.goml index 360e2af8ba42..40f31b2771b2 100644 --- a/src/test/rustdoc-gui/scrape-examples-color.goml +++ b/src/test/rustdoc-gui/scrape-examples-color.goml @@ -6,29 +6,29 @@ define-function: ( "check-colors", (theme, highlight, highlight_focus, help_border, help_color, help_hover_border, help_hover_color), - [ - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", }), - ("reload"), - ("wait-for", ".more-examples-toggle"), - ("assert-css", (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", } + reload: + wait-for: ".more-examples-toggle" + assert-css: (".scraped-example .example-wrap .rust span.highlight:not(.focus)", { "background-color": |highlight|, - }, ALL)), - ("assert-css", (".scraped-example .example-wrap .rust span.highlight.focus", { + }, ALL) + assert-css: (".scraped-example .example-wrap .rust span.highlight.focus", { "background-color": |highlight_focus|, - }, ALL)), + }, ALL) - ("assert-css", (".scraped-example-list .scrape-help", { + assert-css: (".scraped-example-list .scrape-help", { "border-color": |help_border|, "color": |help_color|, - })), - ("move-cursor-to", ".scraped-example-list .scrape-help"), - ("assert-css", (".scraped-example-list .scrape-help:hover", { + }) + move-cursor-to: ".scraped-example-list .scrape-help" + assert-css: (".scraped-example-list .scrape-help:hover", { "border-color": |help_hover_border|, "color": |help_hover_color|, - })), + }) // Moving the cursor to another item to not break next runs. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + } ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml index 8c84fbc0c305..2d5df6a5d25e 100644 --- a/src/test/rustdoc-gui/scrape-examples-toggle.goml +++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml @@ -6,24 +6,24 @@ show-text: true define-function: ( "check-color", (theme, toggle_line_color, toggle_line_hover_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // Clicking "More examples..." will open additional examples - ("assert-attribute-false", (".more-examples-toggle", {"open": ""})), - ("click", ".more-examples-toggle"), - ("assert-attribute", (".more-examples-toggle", {"open": ""})), + assert-attribute-false: (".more-examples-toggle", {"open": ""}) + click: ".more-examples-toggle" + assert-attribute: (".more-examples-toggle", {"open": ""}) - ("assert-css", (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL)), - ("move-cursor-to", ".toggle-line"), - ("assert-css", ( + assert-css: (".toggle-line-inner", {"background-color": |toggle_line_color|}, ALL) + move-cursor-to: ".toggle-line" + assert-css: ( ".toggle-line:hover .toggle-line-inner", {"background-color": |toggle_line_hover_color|}, - )), + ) // Moving cursor away from the toggle line to prevent disrupting next test. - ("move-cursor-to", ".search-input"), - ], + move-cursor-to: ".search-input" + }, ) call-function: ("check-color", { diff --git a/src/test/rustdoc-gui/search-no-result.goml b/src/test/rustdoc-gui/search-no-result.goml index b88be32c94a4..b76a44fa992e 100644 --- a/src/test/rustdoc-gui/search-no-result.goml +++ b/src/test/rustdoc-gui/search-no-result.goml @@ -5,18 +5,18 @@ show-text: true define-function: ( "check-no-result", (theme, link, link_hover), - [ + block { // Changing theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for", "#results"), - ("assert", ".search-failed.active"), - ("assert-css", ("#results a", {"color": |link|}, ALL)), - ("move-cursor-to", "#results a"), - ("assert-css", ("#results a:hover", {"color": |link_hover|})), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for: "#results" + assert: ".search-failed.active" + assert-css: ("#results a", {"color": |link|}, ALL) + move-cursor-to: "#results a" + assert-css: ("#results a:hover", {"color": |link_hover|}) // Moving the cursor to some other place to not create issues with next function run. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + }, ) call-function: ("check-no-result", { diff --git a/src/test/rustdoc-gui/search-result-color.goml b/src/test/rustdoc-gui/search-result-color.goml index 3c5fe9b74b74..d6d54ec4bee9 100644 --- a/src/test/rustdoc-gui/search-result-color.goml +++ b/src/test/rustdoc-gui/search-result-color.goml @@ -3,53 +3,32 @@ define-function: ( "check-result-color", (result_kind, color, hover_color), - [ - ( - "assert-css", - (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL), - ), - ( - "assert-css", - ( - ".result-" + |result_kind|, - {"color": |entry_color|, "background-color": |background_color|}, - ), - ), - ( - "move-cursor-to", + block { + assert-css: (".result-" + |result_kind| + " ." + |result_kind|, {"color": |color|}, ALL) + assert-css: ( ".result-" + |result_kind|, - ), - ( - "assert-css", - ( - ".result-" + |result_kind| + ":hover", - {"color": |hover_entry_color|, "background-color": |hover_background_color|}, - ), - ), - ( - "assert-css", - (".result-" + |result_kind| + ":hover ." + |result_kind|, {"color": |hover_color|}), - ), - ( - "move-cursor-to", - ".search-input", - ), - ( - "focus", - ".result-" + |result_kind|, - ), - ( - "assert-css", - ( - ".result-" + |result_kind| + ":focus", - {"color": |hover_entry_color|, "background-color": |hover_background_color|}, - ), - ), - ( - "assert-css", - (".result-" + |result_kind| + ":focus ." + |result_kind|, {"color": |hover_color|}), - ), - ], + {"color": |entry_color|, "background-color": |background_color|}, + ) + move-cursor-to: ".result-" + |result_kind| + assert-css: ( + ".result-" + |result_kind| + ":hover", + {"color": |hover_entry_color|, "background-color": |hover_background_color|}, + ) + assert-css: ( + ".result-" + |result_kind| + ":hover ." + |result_kind|, + {"color": |hover_color|}, + ) + move-cursor-to: ".search-input" + focus: ".result-" + |result_kind| + assert-css: ( + ".result-" + |result_kind| + ":focus", + {"color": |hover_entry_color|, "background-color": |hover_background_color|}, + ) + assert-css: ( + ".result-" + |result_kind| + ":focus ." + |result_kind|, + {"color": |hover_color|}, + ) + }, ) goto: "file://" + |DOC_PATH| + "/test_docs/index.html?search=coo" @@ -389,20 +368,20 @@ show-text: true define-function: ( "check-alias", (theme, alias, grey), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("write", (".search-input", "thisisanalias")), + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + write: (".search-input", "thisisanalias") // To be SURE that the search will be run. - ("press-key", 'Enter'), + press-key: 'Enter' // Waiting for the search results to appear... - ("wait-for", "#search-tabs"), + wait-for: "#search-tabs" // Checking that the colors for the alias element are the ones expected. - ("assert-css", (".result-name > .alias", {"color": |alias|})), - ("assert-css", (".result-name > .alias > .grey", {"color": |grey|})), + assert-css: (".result-name > .alias", {"color": |alias|}) + assert-css: (".result-name > .alias > .grey", {"color": |grey|}) // Leave the search results to prevent reloading with an already filled search input. - ("press-key", "Escape"), - ], + press-key: "Escape" + }, ) call-function: ("check-alias", { diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index 13a5e4c717b6..43e608228d8e 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -42,17 +42,17 @@ show-text: true define-function: ( "check-filter", (theme, border, filter, hover_border, hover_filter), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for", "#crate-search"), - ("assert-css", ("#crate-search", {"border": "1px solid " + |border|})), - ("assert-css", ("#crate-search-div::after", {"filter": |filter|})), - ("move-cursor-to", "#crate-search"), - ("assert-css", ("#crate-search", {"border": "1px solid " + |hover_border|})), - ("assert-css", ("#crate-search-div::after", {"filter": |hover_filter|})), - ("move-cursor-to", ".search-input"), - ], + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for: "#crate-search" + assert-css: ("#crate-search", {"border": "1px solid " + |border|}) + assert-css: ("#crate-search-div::after", {"filter": |filter|}) + move-cursor-to: "#crate-search" + assert-css: ("#crate-search", {"border": "1px solid " + |hover_border|}) + assert-css: ("#crate-search-div::after", {"filter": |hover_filter|}) + move-cursor-to: ".search-input" + }, ) call-function: ("check-filter", { diff --git a/src/test/rustdoc-gui/search-tab.goml b/src/test/rustdoc-gui/search-tab.goml index c2634a04c8a7..36958f700444 100644 --- a/src/test/rustdoc-gui/search-tab.goml +++ b/src/test/rustdoc-gui/search-tab.goml @@ -7,35 +7,35 @@ define-function: ( (theme, background, background_selected, background_hover, border_bottom, border_bottom_selected, border_bottom_hover, border_top, border_top_selected, border_top_hover), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: // These two commands are used to be sure the search will be run. - ("focus", ".search-input"), - ("press-key", "Enter"), + focus: ".search-input" + press-key: "Enter" - ("wait-for", "#search-tabs"), - ("assert-css", ("#search-tabs > button:not(.selected)", { + wait-for: "#search-tabs" + assert-css: ("#search-tabs > button:not(.selected)", { "background-color": |background|, "border-bottom": |border_bottom|, "border-top": |border_top|, - })), - ("assert-css", ("#search-tabs > button.selected", { + }) + assert-css: ("#search-tabs > button.selected", { "background-color": |background_selected|, "border-bottom": |border_bottom_selected|, "border-top": |border_top_selected|, - })), - ("move-cursor-to", "#search-tabs > button:not(.selected)"), - ("assert-css", ("#search-tabs > button:not(.selected):hover", { + }) + move-cursor-to: "#search-tabs > button:not(.selected)" + assert-css: ("#search-tabs > button:not(.selected):hover", { "background-color": |background_hover|, "border-bottom": |border_bottom_hover|, "border-top": |border_top_hover|, - })), + }) // To prevent disrupting next run of this function. - ("move-cursor-to", ".search-input"), - ], + move-cursor-to: ".search-input" + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-links-color.goml b/src/test/rustdoc-gui/sidebar-links-color.goml index 7ef7ec90cd26..1d5fdb7a48fc 100644 --- a/src/test/rustdoc-gui/sidebar-links-color.goml +++ b/src/test/rustdoc-gui/sidebar-links-color.goml @@ -12,80 +12,80 @@ define-function: ( trait_hover_background, fn, fn_hover, fn_hover_background, type, type_hover, type_hover_background, keyword, keyword_hover, keyword_hover_background, ), - [ - ("local-storage", { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" }), - ("reload"), + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false" } + reload: // Struct - ("assert-css", ( + assert-css: ( ".sidebar .block.struct a:not(.current)", {"color": |struct|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.struct a:not(.current)"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.struct a:not(.current)" + assert-css: ( ".sidebar .block.struct a:hover", {"color": |struct_hover|, "background-color": |struct_hover_background|}, - )), + ) // Enum - ("assert-css", ( + assert-css: ( ".sidebar .block.enum a", {"color": |enum|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.enum a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.enum a" + assert-css: ( ".sidebar .block.enum a:hover", {"color": |enum_hover|, "background-color": |enum_hover_background|}, - )), + ) // Union - ("assert-css", ( + assert-css: ( ".sidebar .block.union a", {"color": |union|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.union a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.union a" + assert-css: ( ".sidebar .block.union a:hover", {"color": |union_hover|, "background-color": |union_hover_background|}, - )), + ) // Trait - ("assert-css", ( + assert-css: ( ".sidebar .block.trait a", {"color": |trait|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.trait a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.trait a" + assert-css: ( ".sidebar .block.trait a:hover", {"color": |trait_hover|, "background-color": |trait_hover_background|}, - )), + ) // Function - ("assert-css", ( + assert-css: ( ".sidebar .block.fn a", {"color": |fn|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.fn a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.fn a" + assert-css: ( ".sidebar .block.fn a:hover", {"color": |fn_hover|, "background-color": |fn_hover_background|}, - )), + ) // Type definition - ("assert-css", ( + assert-css: ( ".sidebar .block.type a", {"color": |type|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.type a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.type a" + assert-css: ( ".sidebar .block.type a:hover", {"color": |type_hover|, "background-color": |type_hover_background|}, - )), + ) // Keyword - ("assert-css", ( + assert-css: ( ".sidebar .block.keyword a", {"color": |keyword|, "background-color": "rgba(0, 0, 0, 0)"}, - )), - ("move-cursor-to", ".sidebar .block.keyword a"), - ("assert-css", ( + ) + move-cursor-to: ".sidebar .block.keyword a" + assert-css: ( ".sidebar .block.keyword a:hover", {"color": |keyword_hover|, "background-color": |keyword_hover_background|}, - )), - ] + ) + } ) call-function: ( diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml index 38d01f7f612a..d5f4b619629e 100644 --- a/src/test/rustdoc-gui/sidebar-mobile.goml +++ b/src/test/rustdoc-gui/sidebar-mobile.goml @@ -58,17 +58,17 @@ show-text: true define-function: ( "check-colors", (theme, color, background), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("reload"), + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + reload: // Open the sidebar menu. - ("click", ".sidebar-menu-toggle"), - ("assert-css", (".sidebar", { + click: ".sidebar-menu-toggle" + assert-css: (".sidebar", { "background-color": |background|, "color": |color|, - })), - ], + }) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index df4506e11196..d74d9420389f 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -35,88 +35,88 @@ define-function: ( theme, color, color_hover, background, background_hover, background_toggle, background_toggle_hover, ), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("wait-for-css", ("#src-sidebar-toggle", {"visibility": "visible"})), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + wait-for-css: ("#src-sidebar-toggle", {"visibility": "visible"}) + assert-css: ( "#source-sidebar details[open] > .files a.selected", {"color": |color_hover|, "background-color": |background|}, - )), + ) // Without hover or focus. - ("assert-css", ("#src-sidebar-toggle > button", {"background-color": |background_toggle|})), + assert-css: ("#src-sidebar-toggle > button", {"background-color": |background_toggle|}) // With focus. - ("focus", "#src-sidebar-toggle > button"), - ("assert-css", ( + focus: "#src-sidebar-toggle > button" + assert-css: ( "#src-sidebar-toggle > button:focus", {"background-color": |background_toggle_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#src-sidebar-toggle > button"), - ("assert-css", ( + move-cursor-to: "#src-sidebar-toggle > button" + assert-css: ( "#src-sidebar-toggle > button:hover", {"background-color": |background_toggle_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar details[open] > .files a:not(.selected)", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar details[open] > .files a:not(.selected)"), - ("wait-for-css", ( + focus: "#source-sidebar details[open] > .files a:not(.selected)" + wait-for-css: ( "#source-sidebar details[open] > .files a:not(.selected):focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar details[open] > .files a:not(.selected)"), - ("assert-css", ( + move-cursor-to: "#source-sidebar details[open] > .files a:not(.selected)" + assert-css: ( "#source-sidebar details[open] > .files a:not(.selected):hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar .dir-entry summary", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar .dir-entry summary"), - ("wait-for-css", ( + focus: "#source-sidebar .dir-entry summary" + wait-for-css: ( "#source-sidebar .dir-entry summary:focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar .dir-entry summary"), - ("assert-css", ( + move-cursor-to: "#source-sidebar .dir-entry summary" + assert-css: ( "#source-sidebar .dir-entry summary:hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), + ) // Without hover or focus. - ("assert-css", ( + assert-css: ( "#source-sidebar details[open] > .folders > details > summary", {"color": |color|, "background-color": |background_toggle|}, - )), + ) // With focus. - ("focus", "#source-sidebar details[open] > .folders > details > summary"), - ("wait-for-css", ( + focus: "#source-sidebar details[open] > .folders > details > summary" + wait-for-css: ( "#source-sidebar details[open] > .folders > details > summary:focus", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ("focus", ".search-input"), + ) + focus: ".search-input" // With hover. - ("move-cursor-to", "#source-sidebar details[open] > .folders > details > summary"), - ("assert-css", ( + move-cursor-to: "#source-sidebar details[open] > .folders > details > summary" + assert-css: ( "#source-sidebar details[open] > .folders > details > summary:hover", {"color": |color_hover|, "background-color": |background_hover|}, - )), - ], + ) + }, ) call-function: ("check-colors", { diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 6bc07fbae04d..3ee83d6f475a 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -7,43 +7,43 @@ show-text: true define-function: ( "check-colors", (theme, color, background_color), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".source .sidebar", { - "color": |color|, - "background-color": |background_color| - }, ALL)), - ], + assert-css: (".source .sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL) + }, ) call-function: ( - "check-colors", - { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background_color": "rgb(20, 25, 31)", - } + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } ) call-function: ( - "check-colors", - { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background_color": "rgb(80, 80, 80)", - } + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } ) call-function: ( - "check-colors", - { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background_color": "rgb(245, 245, 245)", - } + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } ) // Next, desktop mode layout. diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index bfd7567a2242..9db7f59695bb 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -7,43 +7,43 @@ show-text: true define-function: ( "check-colors", (theme, color, background_color), - [ - ("local-storage", { + block { + local-storage: { "rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false", - }), - ("reload"), + } + reload: // Checking results colors. - ("assert-css", (".sidebar", { - "color": |color|, - "background-color": |background_color| - }, ALL)), - ], + assert-css: (".sidebar", { + "color": |color|, + "background-color": |background_color| + }, ALL) + }, ) call-function: ( - "check-colors", - { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background_color": "rgb(20, 25, 31)", - } + "check-colors", + { + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background_color": "rgb(20, 25, 31)", + } ) call-function: ( - "check-colors", - { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background_color": "rgb(80, 80, 80)", - } + "check-colors", + { + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background_color": "rgb(80, 80, 80)", + } ) call-function: ( - "check-colors", - { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background_color": "rgb(245, 245, 245)", - } + "check-colors", + { + "theme": "light", + "color": "rgb(0, 0, 0)", + "background_color": "rgb(245, 245, 245)", + } ) local-storage: {"rustdoc-theme": "light"} diff --git a/src/test/rustdoc-gui/source-code-page.goml b/src/test/rustdoc-gui/source-code-page.goml index e0397890519b..7c35119e6959 100644 --- a/src/test/rustdoc-gui/source-code-page.goml +++ b/src/test/rustdoc-gui/source-code-page.goml @@ -22,20 +22,20 @@ assert-attribute-false: (".src-line-numbers > a:nth-child(7)", {"class": "line-h define-function: ( "check-colors", (theme, color, background_color, highlight_color, highlight_background_color), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ( + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ( ".src-line-numbers > a:not(.line-highlighted)", {"color": |color|, "background-color": |background_color|}, ALL, - )), - ("assert-css", ( + ) + assert-css: ( ".src-line-numbers > a.line-highlighted", {"color": |highlight_color|, "background-color": |highlight_background_color|}, ALL, - )), - ], + ) + }, ) call-function: ("check-colors", { @@ -124,28 +124,28 @@ store-property: ( define-function: ( "check-sidebar-dir-entry", (x, y), - [ - ("assert", "details:first-of-type.dir-entry[open] > summary::marker"), - ("assert-css", ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"})), + block { + assert: "details:first-of-type.dir-entry[open] > summary::marker" + assert-css: ("#source-sidebar > details:first-of-type.dir-entry", {"padding-left": "4px"}) // This check ensures that the summary is only one line. - ("assert-property", ( + assert-property: ( "#source-sidebar > details:first-of-type.dir-entry[open] > summary", {"offsetHeight": |link_height|} - )), - ("assert-position", ( + ) + assert-position: ( "#source-sidebar > details:first-of-type.dir-entry[open] > summary", {"x": |x|, "y": |y|} - )), - ("assert-property", ( + ) + assert-property: ( "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", {"offsetHeight": |link_height|} - )), - ("assert-position", ( + ) + assert-position: ( "#source-sidebar > details:first-of-type.dir-entry[open] > .files > a", // left margin {"x": |x| + 27, "y": |y| + |link_height|} - )), - ] + ) + } ) store-property: ( source_sidebar_title_height, diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml index aaed8440a40b..50ba1ba62dbf 100644 --- a/src/test/rustdoc-gui/stab-badge.goml +++ b/src/test/rustdoc-gui/stab-badge.goml @@ -2,40 +2,40 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" show-text: true define-function: ( - "check-badge", - (theme, background, color), - [ - ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}), - ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"), - ("assert", (".docblock .stab")), - ("assert", (".item-table .stab")), - ("assert-css", (".stab", { - "border-radius": "3px", - "color": |color|, - "background-color": |background|, - })), - ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"), - ("assert", (".item-info .stab")), - ("assert-css", (".stab", { - "border-radius": "3px", - "color": |color|, - "background-color": |background|, - })), - ] + "check-badge", + (theme, background, color), + block { + local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|} + goto: "file://" + |DOC_PATH| + "/test_docs/index.html" + assert: ".docblock .stab" + assert: ".item-table .stab" + assert-css: (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + }) + goto: "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html" + assert: (".item-info .stab") + assert-css: (".stab", { + "border-radius": "3px", + "color": |color|, + "background-color": |background|, + }) + }, ) call-function: ("check-badge", { - "theme": "ayu", - "color": "rgb(197, 197, 197)", - "background": "rgb(49, 69, 89)", + "theme": "ayu", + "color": "rgb(197, 197, 197)", + "background": "rgb(49, 69, 89)", }) call-function: ("check-badge", { - "theme": "dark", - "color": "rgb(221, 221, 221)", - "background": "rgb(49, 69, 89)", + "theme": "dark", + "color": "rgb(221, 221, 221)", + "background": "rgb(49, 69, 89)", }) call-function: ("check-badge", { - "theme": "light", - "color": "rgb(0, 0, 0)", - "background": "rgb(255, 245, 214)", + "theme": "light", + "color": "rgb(0, 0, 0)", + "background": "rgb(255, 245, 214)", }) diff --git a/src/test/rustdoc-gui/target.goml b/src/test/rustdoc-gui/target.goml index 3e5c30dc7eaf..ca393ee58917 100644 --- a/src/test/rustdoc-gui/target.goml +++ b/src/test/rustdoc-gui/target.goml @@ -8,14 +8,14 @@ assert: "#method\.a_method:target" define-function: ( "check-style", (theme, background, border), - [ - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), - ("reload"), - ("assert-css", ("#method\.a_method:target", { + block { + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} + reload: + assert-css: ("#method\.a_method:target", { "background-color": |background|, "border-right": "3px solid " + |border|, - })), - ], + }) + }, ) call-function: ("check-style", { diff --git a/src/test/rustdoc-gui/toggle-docs.goml b/src/test/rustdoc-gui/toggle-docs.goml index 45bb8daf1f20..89ce78e3aab4 100644 --- a/src/test/rustdoc-gui/toggle-docs.goml +++ b/src/test/rustdoc-gui/toggle-docs.goml @@ -50,24 +50,24 @@ show-text: true define-function: ( "check-color", (theme, filter), - [ + block { // Setting the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), + reload: - ("assert-css", ("details.rustdoc-toggle > summary::before", { + assert-css: ("details.rustdoc-toggle > summary::before", { "opacity": "0.5", "filter": |filter|, - }, ALL)), - ("move-cursor-to", "details.rustdoc-toggle summary"), - ("assert-css", ("details.rustdoc-toggle > summary:hover::before", { + }, ALL) + move-cursor-to: "details.rustdoc-toggle summary" + assert-css: ("details.rustdoc-toggle > summary:hover::before", { "opacity": "1", "filter": |filter|, - })), + }) // moving the cursor somewhere else to not mess with next function calls. - ("move-cursor-to", ".search-input"), - ] + move-cursor-to: ".search-input" + }, ) call-function: ("check-color", {"theme": "ayu", "filter": "invert(1)"}) diff --git a/src/test/rustdoc-gui/unsafe-fn.goml b/src/test/rustdoc-gui/unsafe-fn.goml index 5e43b85fce08..d3a672ddde6e 100644 --- a/src/test/rustdoc-gui/unsafe-fn.goml +++ b/src/test/rustdoc-gui/unsafe-fn.goml @@ -14,13 +14,13 @@ define-function: ( // `theme` is the theme being tested. // `color` is the expected color of the `` element. (theme, color), - [ + block { // Set the theme. - ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), + local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"} // We reload the page so the local storage settings are being used. - ("reload"), - ("assert-css", (".item-left sup", {"color": |color|})), - ], + reload: + assert-css: (".item-left sup", {"color": |color|}) + }, ) call-function: ("sup-check", ("dark", "rgb(221, 221, 221)")) From ff46d116c1fec1a1ceb988e0e31263c00a5d521b Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 6 Jan 2023 17:57:03 +0000 Subject: [PATCH 184/223] rustdoc: Strip imports of items which are `#[doc(hidden)]` Closes #106379 --- src/librustdoc/clean/types.rs | 11 +++++++++++ src/librustdoc/passes/stripper.rs | 1 + src/test/rustdoc-json/doc_hidden_failure.rs | 3 ++- .../rustdoc-json/reexport/pub_use_doc_hidden.rs | 15 +++++++++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 6d55a6794f58..827afafbba3b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -2494,6 +2494,17 @@ impl Import { pub(crate) fn new_glob(source: ImportSource, should_be_displayed: bool) -> Self { Self { kind: ImportKind::Glob, source, should_be_displayed } } + + pub(crate) fn imported_item_is_doc_hidden(&self, tcx: TyCtxt<'_>) -> bool { + match self.source.did { + Some(did) => tcx + .get_attrs(did, sym::doc) + .filter_map(ast::Attribute::meta_item_list) + .flatten() + .has_word(sym::hidden), + None => false, + } + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/passes/stripper.rs b/src/librustdoc/passes/stripper.rs index bf111133b9f7..f8a0d77538d3 100644 --- a/src/librustdoc/passes/stripper.rs +++ b/src/librustdoc/passes/stripper.rs @@ -248,6 +248,7 @@ pub(crate) struct ImportStripper<'tcx> { impl<'tcx> DocFolder for ImportStripper<'tcx> { fn fold_item(&mut self, i: Item) -> Option { match *i.kind { + clean::ImportItem(imp) if imp.imported_item_is_doc_hidden(self.tcx) => None, clean::ExternCrateItem { .. } | clean::ImportItem(..) if i.visibility(self.tcx) != Some(Visibility::Public) => { diff --git a/src/test/rustdoc-json/doc_hidden_failure.rs b/src/test/rustdoc-json/doc_hidden_failure.rs index 6573166c47f2..0d2c6b2209bd 100644 --- a/src/test/rustdoc-json/doc_hidden_failure.rs +++ b/src/test/rustdoc-json/doc_hidden_failure.rs @@ -14,7 +14,8 @@ mod auto { } } -// @count "$.index[*][?(@.name=='builders')]" 2 +// @count "$.index[*][?(@.name=='builders')]" 1 +// @has "$.index[*][?(@.name == 'ActionRowBuilder')"] pub use auto::*; pub mod builders { diff --git a/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs b/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs new file mode 100644 index 000000000000..a2a25d08448a --- /dev/null +++ b/src/test/rustdoc-json/reexport/pub_use_doc_hidden.rs @@ -0,0 +1,15 @@ +// Regression test for + +#![feature(no_core)] +#![no_core] + +mod repeat_n { + #[doc(hidden)] + pub struct RepeatN {} +} + +pub use repeat_n::RepeatN; + +// @count "$.index[*][?(@.name=='pub_use_doc_hidden')].inner.items[*]" 0 +// @!has "$.index[*][?(@.kind=='struct')]" +// @!has "$.index[*][?(@.kind=='import')]" From 5cda0a2f39930daaeb1e71e9027be0e28fe55cfd Mon Sep 17 00:00:00 2001 From: Matthew Esposito Date: Fri, 6 Jan 2023 14:07:12 -0500 Subject: [PATCH 185/223] Add default and latest stable edition to --edition in rustc --- compiler/rustc_session/src/config.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index a87e820386e7..233343febffd 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -35,6 +35,7 @@ use std::hash::Hash; use std::iter; use std::path::{Path, PathBuf}; use std::str::{self, FromStr}; +use std::sync::LazyLock; pub mod sigpipe; @@ -1322,7 +1323,12 @@ mod opt { unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) } } - +static EDITION_STRING: LazyLock = LazyLock::new(|| { + format!( + "Specify which edition of the compiler to use when compiling code.\ +The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}." + ) +}); /// Returns the "short" subset of the rustc command line options, /// including metadata for each option, such as whether the option is /// part of the stable long-term interface for rustc. @@ -1355,7 +1361,7 @@ pub fn rustc_short_optgroups() -> Vec { opt::opt_s( "", "edition", - "Specify which edition of the compiler to use when compiling code.", + &*EDITION_STRING, EDITION_NAME_LIST, ), opt::multi_s( From d5e5762211a6c8ee22b789c15596d2b49a45ed3f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 3 Jan 2023 18:18:06 +0100 Subject: [PATCH 186/223] Handle non-existant upstream master branches in `x fmt` --- Cargo.lock | 1 - src/bootstrap/format.rs | 52 +++++++++++++++++++++---------- src/bootstrap/util.rs | 17 ++++++++++ src/tools/build_helper/src/git.rs | 49 +++++++++++++++++++++++++++-- 4 files changed, 99 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a86a1012a76..bfca4531c18c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5308,7 +5308,6 @@ dependencies = [ name = "tidy" version = "0.1.0" dependencies = [ - "build_helper", "cargo_metadata 0.14.0", "ignore", "lazy_static", diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index cca45f4a634e..bfc57a85cdb4 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -1,8 +1,8 @@ //! Runs rustfmt on the repository. use crate::builder::Builder; -use crate::util::{output, program_out_of_date, t}; -use build_helper::git::get_rust_lang_rust_remote; +use crate::util::{output, output_result, program_out_of_date, t}; +use build_helper::git::updated_master_branch; use ignore::WalkBuilder; use std::collections::VecDeque; use std::path::{Path, PathBuf}; @@ -79,21 +79,24 @@ fn update_rustfmt_version(build: &Builder<'_>) { /// rust-lang/master and what is now on the disk. /// /// Returns `None` if all files should be formatted. -fn get_modified_rs_files(build: &Builder<'_>) -> Option> { - let Ok(remote) = get_rust_lang_rust_remote() else { return None; }; +fn get_modified_rs_files(build: &Builder<'_>) -> Result>, String> { + let Ok(updated_master) = updated_master_branch(Some(&build.config.src)) else { return Ok(None); }; + if !verify_rustfmt_version(build) { - return None; + return Ok(None); } let merge_base = - output(build.config.git().arg("merge-base").arg(&format!("{remote}/master")).arg("HEAD")); - Some( - output(build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim())) - .lines() - .map(|s| s.trim().to_owned()) - .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs")) - .collect(), - ) + output_result(build.config.git().arg("merge-base").arg(&updated_master).arg("HEAD"))?; + Ok(Some( + output_result( + build.config.git().arg("diff-index").arg("--name-only").arg(merge_base.trim()), + )? + .lines() + .map(|s| s.trim().to_owned()) + .filter(|f| Path::new(f).extension().map_or(false, |ext| ext == "rs")) + .collect(), + )) } #[derive(serde::Deserialize)] @@ -130,6 +133,9 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { Ok(status) => status.success(), Err(_) => false, }; + + let mut paths = paths.to_vec(); + if git_available { let in_working_tree = match build .config @@ -163,10 +169,21 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { ignore_fmt.add(&format!("!/{}", untracked_path)).expect(&untracked_path); } if !check && paths.is_empty() { - if let Some(files) = get_modified_rs_files(build) { - for file in files { - println!("formatting modified file {file}"); - ignore_fmt.add(&format!("/{file}")).expect(&file); + match get_modified_rs_files(build) { + Ok(Some(files)) => { + for file in files { + println!("formatting modified file {file}"); + ignore_fmt.add(&format!("/{file}")).expect(&file); + } + } + Ok(None) => {} + Err(err) => { + println!( + "WARN: Something went wrong when running git commands:\n{err}\n\ + Falling back to formatting all files." + ); + // Something went wrong when getting the version. Just format all the files. + paths.push(".".into()); } } } @@ -176,6 +193,7 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) { } else { println!("Could not find usable git. Skipping git-aware format checks"); } + let ignore_fmt = ignore_fmt.build().unwrap(); let rustfmt_path = build.initial_rustfmt().unwrap_or_else(|| { diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 8ce9a9ce38cc..93e53d383cd3 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -412,6 +412,23 @@ pub fn output(cmd: &mut Command) -> String { String::from_utf8(output.stdout).unwrap() } +pub fn output_result(cmd: &mut Command) -> Result { + let output = match cmd.stderr(Stdio::inherit()).output() { + Ok(status) => status, + Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)), + }; + if !output.status.success() { + return Err(format!( + "command did not execute successfully: {:?}\n\ + expected success, got: {}\n{}", + cmd, + output.status, + String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? + )); + } + Ok(String::from_utf8(output.stdout).map_err(|err| format!("{err:?}"))?) +} + /// Returns the last-modified time for `path`, or zero if it doesn't exist. pub fn mtime(path: &Path) -> SystemTime { fs::metadata(path).and_then(|f| f.modified()).unwrap_or(UNIX_EPOCH) diff --git a/src/tools/build_helper/src/git.rs b/src/tools/build_helper/src/git.rs index e9638206e672..dc62051cb85d 100644 --- a/src/tools/build_helper/src/git.rs +++ b/src/tools/build_helper/src/git.rs @@ -1,4 +1,4 @@ -use std::process::Command; +use std::{path::Path, process::Command}; /// Finds the remote for rust-lang/rust. /// For example for these remotes it will return `upstream`. @@ -8,8 +8,11 @@ use std::process::Command; /// upstream https://github.com/rust-lang/rust (fetch) /// upstream https://github.com/rust-lang/rust (push) /// ``` -pub fn get_rust_lang_rust_remote() -> Result { +pub fn get_rust_lang_rust_remote(git_dir: Option<&Path>) -> Result { let mut git = Command::new("git"); + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } git.args(["config", "--local", "--get-regex", "remote\\..*\\.url"]); let output = git.output().map_err(|err| format!("{err:?}"))?; @@ -28,3 +31,45 @@ pub fn get_rust_lang_rust_remote() -> Result { rust_lang_remote.split('.').nth(1).ok_or_else(|| "remote name not found".to_owned())?; Ok(remote_name.into()) } + +pub fn rev_exists(rev: &str, git_dir: Option<&Path>) -> Result { + let mut git = Command::new("git"); + if let Some(git_dir) = git_dir { + git.current_dir(git_dir); + } + git.args(["rev-parse", rev]); + let output = git.output().map_err(|err| format!("{err:?}"))?; + + match output.status.code() { + Some(0) => Ok(true), + Some(128) => Ok(false), + None => { + return Err(format!( + "git didn't exit properly: {}", + String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? + )); + } + Some(code) => { + return Err(format!( + "git command exited with status code: {code}: {}", + String::from_utf8(output.stderr).map_err(|err| format!("{err:?}"))? + )); + } + } +} + +/// Returns the master branch from which we can take diffs to see changes. +/// This will usually be rust-lang/rust master, but sometimes this might not exist. +/// This could be because the user is updating their forked master branch using the GitHub UI +/// and therefore doesn't need an upstream master branch checked out. +/// We will then fall back to origin/master in the hope that at least this exists. +pub fn updated_master_branch(git_dir: Option<&Path>) -> Result { + let upstream_remote = get_rust_lang_rust_remote(git_dir)?; + let upstream_master = format!("{upstream_remote}/master"); + if rev_exists(&upstream_master, git_dir)? { + return Ok(upstream_master); + } + + // We could implement smarter logic here in the future. + Ok("origin/master".into()) +} From 893938f64f7a9ff531b3968c9a9e79e0524606bd Mon Sep 17 00:00:00 2001 From: Matthew E Date: Fri, 6 Jan 2023 14:36:52 -0500 Subject: [PATCH 187/223] Update compiler/rustc_session/src/config.rs Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- compiler/rustc_session/src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 233343febffd..1ccfc59f7a9d 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1325,7 +1325,7 @@ mod opt { } static EDITION_STRING: LazyLock = LazyLock::new(|| { format!( - "Specify which edition of the compiler to use when compiling code.\ + "Specify which edition of the compiler to use when compiling code. \ The default is {DEFAULT_EDITION} and the latest stable edition is {LATEST_STABLE_EDITION}." ) }); From 16a3c8032e634d3da53f8d4c0a875f369a9d4394 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 6 Jan 2023 12:20:03 -0700 Subject: [PATCH 188/223] rustdoc: remove no-op CSS `.rustdoc.source .sidebar { width: 0 }` This CSS was added in dc2c9723343c985740be09919236a6e96c4e4433, before 6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c when the sidebars were merged. Now that they are merged, the source sidebar is being pushed off-screen anyway, so giving it zero width doesn't do much. --- src/librustdoc/html/static/css/rustdoc.css | 6 +----- src/test/rustdoc-gui/sidebar-source-code-display.goml | 6 +++--- src/test/rustdoc-gui/sidebar-source-code.goml | 6 +++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 05a12d3d4d4a..d77b65ac6034 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1598,14 +1598,10 @@ in storage.js .sidebar.shown, .source-sidebar-expanded .source .sidebar, - .sidebar:focus-within { + .rustdoc:not(.source) .sidebar:focus-within { left: 0; } - .rustdoc.source > .sidebar { - width: 0; - } - .mobile-topbar h2 { padding-bottom: 0; margin: auto 0.5em auto auto; diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index df4506e11196..d0e2c8a6adc2 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -171,15 +171,15 @@ assert-css: ( // We now check that the scroll position is kept when opening the sidebar. click: "#src-sidebar-toggle" -wait-for-css: (".sidebar", {"width": "0px"}) +wait-for-css: (".sidebar", {"left": "-1000px"}) // We scroll to line 117 to change the scroll position. scroll-to: '//*[@id="117"]' assert-window-property: {"pageYOffset": "2542"} // Expanding the sidebar... click: "#src-sidebar-toggle" -wait-for-css: (".sidebar", {"width": "500px"}) +wait-for-css: (".sidebar", {"left": "0px"}) click: "#src-sidebar-toggle" -wait-for-css: (".sidebar", {"width": "0px"}) +wait-for-css: (".sidebar", {"left": "-1000px"}) // The "scrollTop" property should be the same. assert-window-property: {"pageYOffset": "2542"} diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml index 6bc07fbae04d..08a237e49dae 100644 --- a/src/test/rustdoc-gui/sidebar-source-code.goml +++ b/src/test/rustdoc-gui/sidebar-source-code.goml @@ -77,11 +77,11 @@ assert-count: ("//*[@id='source-sidebar']/details[not(text()='lib2') and not(@op // We now switch to mobile mode. size: (600, 600) -wait-for-css: (".source-sidebar-expanded nav.sidebar", {"width": "600px"}) +wait-for-css: (".source-sidebar-expanded nav.sidebar", {"left": "0px"}) // We collapse the sidebar. click: (10, 10) -// We check that the sidebar has the expected width (0). -assert-css: ("nav.sidebar", {"width": "0px"}) +// We check that the sidebar has been moved off-screen. +assert-css: ("nav.sidebar", {"left": "-1000px"}) // We ensure that the class has been removed. assert-false: ".source-sidebar-expanded" assert: "nav.sidebar" From e7a777805a63266292bb715e283db4107fb6e394 Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 3 Jan 2023 13:27:49 +0800 Subject: [PATCH 189/223] Suggest possible clone when we have &T --- compiler/rustc_hir_typeck/src/demand.rs | 1 + .../src/fn_ctxt/suggestions.rs | 29 ++++++++ .../src/traits/error_reporting/mod.rs | 5 ++ .../src/traits/error_reporting/suggestions.rs | 72 ++++++++++++++++++- .../issue-106443-sugg-clone-for-arg.rs | 23 ++++++ .../issue-106443-sugg-clone-for-arg.stderr | 35 +++++++++ .../issue-106443-sugg-clone-for-bound.rs | 20 ++++++ .../issue-106443-sugg-clone-for-bound.stderr | 29 ++++++++ 8 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs create mode 100644 src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr create mode 100644 src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs create mode 100644 src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0f191c21a0a6..52778747987d 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -57,6 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty) || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected) || self.suggest_copied_or_cloned(err, expr, expr_ty, expected) + || self.suggest_clone_for_ref(err, expr, expr_ty, expected) || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected); if !suggested { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 066e98c74578..991b0399542b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1014,6 +1014,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + pub(crate) fn suggest_clone_for_ref( + &self, + diag: &mut Diagnostic, + expr: &hir::Expr<'_>, + expr_ty: Ty<'tcx>, + expected_ty: Ty<'tcx>, + ) -> bool { + if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind() && + let Some(clone_trait_def) = self.tcx.lang_items().clone_trait() && + expected_ty == *inner_ty && + self + .infcx + .type_implements_trait( + clone_trait_def, + [self.tcx.erase_regions(expected_ty)], + self.param_env + ) + .must_apply_modulo_regions() { + diag.span_suggestion_verbose( + expr.span.shrink_to_hi(), + "consider using clone here", + ".clone()", + Applicability::MachineApplicable, + ); + return true; + } + false + } + pub(crate) fn suggest_copied_or_cloned( &self, diag: &mut Diagnostic, 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 17331a501055..9c098e1a2fc1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -873,6 +873,11 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); } + if self.suggest_add_clone_to_arg(&obligation, &mut err, trait_predicate) { + err.emit(); + return; + } + if self.suggest_impl_trait(&mut err, span, &obligation, trait_predicate) { err.emit(); return; 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 28f76b141469..d15196a9577a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -10,7 +10,7 @@ use crate::infer::InferCtxt; use crate::traits::{NormalizeExt, ObligationCtxt}; use hir::def::CtorOf; -use hir::HirId; +use hir::{Expr, HirId}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{ @@ -206,11 +206,15 @@ pub trait TypeErrCtxtExt<'tcx> { trait_pred: ty::PolyTraitPredicate<'tcx>, ); - fn suggest_add_reference_to_arg( + fn suggest_add_clone_to_arg( &self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, + ); + + fn suggest_add_reference_to_arg( + err: &mut Diagnostic, has_custom_message: bool, ) -> bool; @@ -1102,6 +1106,70 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } + fn suggest_add_clone_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, + ) -> bool { + let span = obligation.cause.span; + let body_id = obligation.cause.body_id; + let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); + let ty = self.tcx.erase_late_bound_regions(self_ty); + let owner = self.tcx.hir().get_parent_item(body_id); + if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() && + let arg_node = self.tcx.hir().get(*arg_hir_id) && + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node && + let Some(generics) = self.tcx.hir().get_generics(owner.def_id) && + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() && + let ty::Param(param) = inner_ty.kind() && + let Some(generic_param) = + generics.params.iter().find(|p| p.name.ident().as_str() == param.name.as_str()) + { + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = self + .type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions(); + + let trait_pred_and_suggested_ty = + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred_and_suggested_ty, + ); + + if has_clone && self.predicate_may_hold(&new_obligation) { + let clone_bound = generics.bounds_for_param(generic_param.def_id) + .flat_map(|bp| bp.bounds) + .any(|bound| { + if let hir::GenericBound::Trait( hir::PolyTraitRef { trait_ref, ..}, ..) = bound { + Some(clone_trait) == trait_ref.trait_def_id() + } else { + false + } + }); + if !clone_bound { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait) + ); + } + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, + ); + return true; + } + } + false + } + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs new file mode 100644 index 000000000000..48efdb82c46c --- /dev/null +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.rs @@ -0,0 +1,23 @@ +#[derive(Clone)] +struct S; + +// without Clone +struct T; + +fn foo(_: S) {} + +fn test1() { + let s = &S; + foo(s); //~ ERROR mismatched types +} + +fn bar(_: T) {} +fn test2() { + let t = &T; + bar(t); //~ ERROR mismatched types +} + +fn main() { + test1(); + test2(); +} diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr new file mode 100644 index 000000000000..1e66fe3af241 --- /dev/null +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-arg.stderr @@ -0,0 +1,35 @@ +error[E0308]: mismatched types + --> $DIR/issue-106443-sugg-clone-for-arg.rs:11:9 + | +LL | foo(s); + | --- ^ expected struct `S`, found `&S` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-106443-sugg-clone-for-arg.rs:7:4 + | +LL | fn foo(_: S) {} + | ^^^ ---- +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error[E0308]: mismatched types + --> $DIR/issue-106443-sugg-clone-for-arg.rs:17:9 + | +LL | bar(t); + | --- ^ expected struct `T`, found `&T` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/issue-106443-sugg-clone-for-arg.rs:14:4 + | +LL | fn bar(_: T) {} + | ^^^ ---- + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs new file mode 100644 index 000000000000..4e4d4c044c98 --- /dev/null +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs @@ -0,0 +1,20 @@ +#[derive(Clone)] +struct S; + +trait X {} + +impl X for S {} + +fn foo(_: T) {} +fn bar(s: &T) { + foo(s); //~ ERROR the trait bound `&T: X` is not satisfied +} + +fn bar_with_clone(s: &T) { + foo(s); //~ ERROR the trait bound `&T: X` is not satisfied +} + +fn main() { + let s = &S; + bar(s); +} diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr new file mode 100644 index 000000000000..22bafc6cc8b9 --- /dev/null +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&T: X` is not satisfied + --> $DIR/issue-106443-sugg-clone-for-bound.rs:10:9 + | +LL | foo(s); + | ^ the trait `X` is not implemented for `&T` + | +help: consider further restricting this bound + | +LL | fn bar(s: &T) { + | +++++++ +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error[E0277]: the trait bound `&T: X` is not satisfied + --> $DIR/issue-106443-sugg-clone-for-bound.rs:14:9 + | +LL | foo(s); + | ^ the trait `X` is not implemented for `&T` + | +help: consider using clone here + | +LL | foo(s.clone()); + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From 1a0a6132a8f4f3d54971c11c74035c5872a72a1f Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 6 Jan 2023 15:03:05 +0800 Subject: [PATCH 190/223] Apply suggestions from code review Co-authored-by: Esteban Kuber --- .../src/fn_ctxt/suggestions.rs | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 991b0399542b..236bdc60e677 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1021,25 +1021,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr_ty: Ty<'tcx>, expected_ty: Ty<'tcx>, ) -> bool { - if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind() && - let Some(clone_trait_def) = self.tcx.lang_items().clone_trait() && - expected_ty == *inner_ty && - self + if let ty::Ref(_, inner_ty, hir::Mutability::Not) = expr_ty.kind() + && let Some(clone_trait_def) = self.tcx.lang_items().clone_trait() + && expected_ty == *inner_ty + && self .infcx .type_implements_trait( clone_trait_def, [self.tcx.erase_regions(expected_ty)], self.param_env ) - .must_apply_modulo_regions() { - diag.span_suggestion_verbose( - expr.span.shrink_to_hi(), - "consider using clone here", - ".clone()", - Applicability::MachineApplicable, - ); - return true; - } + .must_apply_modulo_regions() + { + diag.span_suggestion_verbose( + expr.span.shrink_to_hi(), + "consider using clone here", + ".clone()", + Applicability::MachineApplicable, + ); + return true; + } false } From ce4afed2efdaaceb2624021df3a8d8fff892415a Mon Sep 17 00:00:00 2001 From: yukang Date: Fri, 6 Jan 2023 07:44:10 +0800 Subject: [PATCH 191/223] comments feedback --- .../src/traits/error_reporting/suggestions.rs | 99 ++++++++++--------- 1 file 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 d15196a9577a..727bdc391bb4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -211,10 +211,13 @@ pub trait TypeErrCtxtExt<'tcx> { obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, - ); + ) -> bool; fn suggest_add_reference_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic, + trait_pred: ty::PolyTraitPredicate<'tcx>, has_custom_message: bool, ) -> bool; @@ -1112,60 +1115,58 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { err: &mut Diagnostic, trait_pred: ty::PolyTraitPredicate<'tcx>, ) -> bool { - let span = obligation.cause.span; - let body_id = obligation.cause.body_id; let self_ty = self.resolve_vars_if_possible(trait_pred.self_ty()); let ty = self.tcx.erase_late_bound_regions(self_ty); - let owner = self.tcx.hir().get_parent_item(body_id); - if let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() && - let arg_node = self.tcx.hir().get(*arg_hir_id) && - let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node && - let Some(generics) = self.tcx.hir().get_generics(owner.def_id) && - let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() && - let ty::Param(param) = inner_ty.kind() && - let Some(generic_param) = - generics.params.iter().find(|p| p.name.ident().as_str() == param.name.as_str()) - { - let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); - let has_clone = self - .type_implements_trait(clone_trait, [ty], obligation.param_env) - .must_apply_modulo_regions(); + let owner = self.tcx.hir().get_parent_item(obligation.cause.body_id); + let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false }; + let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; + let ty::Param(param) = inner_ty.kind() else { return false }; + let Some(generic_param) = generics.get_named(param.name) else { return false }; + let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false }; + let arg_node = self.tcx.hir().get(*arg_hir_id); + let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false }; - let trait_pred_and_suggested_ty = - trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)); - let new_obligation = self.mk_trait_obligation_with_new_self_ty( - obligation.param_env, - trait_pred_and_suggested_ty, - ); + let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); + let has_clone = self + .type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions(); - if has_clone && self.predicate_may_hold(&new_obligation) { - let clone_bound = generics.bounds_for_param(generic_param.def_id) - .flat_map(|bp| bp.bounds) - .any(|bound| { - if let hir::GenericBound::Trait( hir::PolyTraitRef { trait_ref, ..}, ..) = bound { - Some(clone_trait) == trait_ref.trait_def_id() - } else { - false - } - }); - if !clone_bound { - suggest_constraining_type_param( - self.tcx, - generics, - err, - param.name.as_str(), - "Clone", - Some(clone_trait) - ); - } - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider using clone here", - ".clone()".to_string(), - Applicability::MaybeIncorrect, + let trait_pred_and_suggested_ty = + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)); + let new_obligation = self.mk_trait_obligation_with_new_self_ty( + obligation.param_env, + trait_pred_and_suggested_ty, + ); + + if has_clone && self.predicate_may_hold(&new_obligation) { + let clone_bound = generics + .bounds_for_param(generic_param.def_id) + .flat_map(|bp| bp.bounds) + .any(|bound| { + if let hir::GenericBound::Trait(hir::PolyTraitRef { trait_ref, .. }, ..) = bound + { + Some(clone_trait) == trait_ref.trait_def_id() + } else { + false + } + }); + if !clone_bound { + suggest_constraining_type_param( + self.tcx, + generics, + err, + param.name.as_str(), + "Clone", + Some(clone_trait), ); - return true; } + err.span_suggestion_verbose( + obligation.cause.span.shrink_to_hi(), + "consider using clone here", + ".clone()".to_string(), + Applicability::MaybeIncorrect, + ); + return true; } false } From 1eb828ecb1675073c7995db80be2e63719fd73c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Jan 2023 21:28:03 -0800 Subject: [PATCH 192/223] Structured suggestion for `&mut dyn Iterator` when possible Fix #37914. --- compiler/rustc_hir_typeck/src/method/mod.rs | 4 +-- .../rustc_hir_typeck/src/method/suggest.rs | 31 +++++++++++++++++-- .../mutability-mismatch-arg.fixed | 9 ++++++ .../mutability-mismatch-arg.rs | 9 ++++++ .../mutability-mismatch-arg.stderr | 16 ++++++++++ .../mutability-mismatch.rs | 4 +-- .../mutability-mismatch.stderr | 4 +-- .../suggestions/imm-ref-trait-object.stderr | 5 ++- 8 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed create mode 100644 src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs create mode 100644 src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index b9b27e8627af..f3c43e3f4973 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -57,7 +57,7 @@ pub enum MethodError<'tcx> { PrivateMatch(DefKind, DefId, Vec), // Found a `Self: Sized` bound where `Self` is a trait object. - IllegalSizedBound(Vec, bool, Span), + IllegalSizedBound(Vec, bool, Span, &'tcx hir::Expr<'tcx>), // Found a match, but the return type is wrong BadReturnType, @@ -236,7 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => Vec::new(), }; - return Err(IllegalSizedBound(candidates, needs_mut, span)); + return Err(IllegalSizedBound(candidates, needs_mut, span, self_expr)); } Ok(result.callee) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1a42f9d07b18..5a43db69fd49 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => { + MethodError::IllegalSizedBound(candidates, needs_mut, bound_span, self_expr) => { let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); let mut err = self.sess().struct_span_err(span, &msg); err.span_label(bound_span, "this has a `Sized` requirement"); @@ -197,7 +197,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { *region, ty::TypeAndMut { ty: *t_type, mutbl: mutability.invert() }, ); - err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); + let msg = format!("you need `{}` instead of `{}`", trait_type, rcvr_ty); + let mut kind = &self_expr.kind; + while let hir::ExprKind::AddrOf(_, _, expr) + | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind + { + kind = &expr.kind; + } + if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind + && let hir::def::Res::Local(hir_id) = path.res + && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) + && let Some(hir::Node::Param(param)) = self.tcx.hir().find(parent_hir_id) + && let parent_hir_id = self.tcx.hir().get_parent_node(param.hir_id) + && let Some(node) = self.tcx.hir().find(parent_hir_id) + && let Some(decl) = node.fn_decl() + && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == param.ty_span) + && let hir::TyKind::Ref(_, mut_ty) = &ty.kind + && let hir::Mutability::Not = mut_ty.mutbl + { + err.span_suggestion_verbose( + mut_ty.ty.span.shrink_to_lo(), + &msg, + "mut ", + Applicability::MachineApplicable, + ); + } else { + err.help(&msg); + } } } err.emit(); diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed new file mode 100644 index 000000000000..260ef5458d4b --- /dev/null +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed @@ -0,0 +1,9 @@ +// run-rustfix +fn test(t: &mut dyn Iterator) -> u64 { + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs new file mode 100644 index 000000000000..7a1656507f2c --- /dev/null +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs @@ -0,0 +1,9 @@ +// run-rustfix +fn test(t: &dyn Iterator) -> u64 { + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr new file mode 100644 index 000000000000..9b4b9b65d104 --- /dev/null +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr @@ -0,0 +1,16 @@ +error: the `min` method cannot be invoked on a trait object + --> $DIR/mutability-mismatch-arg.rs:3:9 + | +LL | *t.min().unwrap() + | ^^^ + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | + = note: this has a `Sized` requirement + | +help: you need `&mut dyn Iterator` instead of `&dyn Iterator` + | +LL | fn test(t: &mut dyn Iterator) -> u64 { + | +++ + +error: aborting due to previous error + diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs index deb84f6fe97c..aa9b3d038914 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs @@ -27,8 +27,8 @@ impl Trait for Type { fn main() { (&MutType as &dyn MutTrait).function(); //~^ ERROR the `function` method cannot be invoked on a trait object - //~| NOTE you need `&mut dyn MutTrait` instead of `&dyn MutTrait` + //~| HELP you need `&mut dyn MutTrait` instead of `&dyn MutTrait` (&mut Type as &mut dyn Trait).function(); //~^ ERROR the `function` method cannot be invoked on a trait object - //~| NOTE you need `&dyn Trait` instead of `&mut dyn Trait` + //~| HELP you need `&dyn Trait` instead of `&mut dyn Trait` } diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr index dbbf79a4f1a0..0120b9f91e94 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr @@ -7,7 +7,7 @@ LL | Self: Sized; LL | (&MutType as &dyn MutTrait).function(); | ^^^^^^^^ | - = note: you need `&mut dyn MutTrait` instead of `&dyn MutTrait` + = help: you need `&mut dyn MutTrait` instead of `&dyn MutTrait` error: the `function` method cannot be invoked on a trait object --> $DIR/mutability-mismatch.rs:31:35 @@ -18,7 +18,7 @@ LL | Self: Sized; LL | (&mut Type as &mut dyn Trait).function(); | ^^^^^^^^ | - = note: you need `&dyn Trait` instead of `&mut dyn Trait` + = help: you need `&dyn Trait` instead of `&mut dyn Trait` error: aborting due to 2 previous errors diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr index 7791b308d5d0..02847ed8c4c6 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -7,7 +7,10 @@ LL | t.min().unwrap() | = note: this has a `Sized` requirement | - = note: you need `&mut dyn Iterator` instead of `&dyn Iterator` +help: you need `&mut dyn Iterator` instead of `&dyn Iterator` + | +LL | fn test(t: &mut dyn Iterator) -> u64 { + | +++ error: aborting due to previous error From 670a6f1ef5d895d8b9ef5bba6f71576a4428b47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 2 Jan 2023 09:55:13 -0800 Subject: [PATCH 193/223] Change wording to avoid being misleading --- compiler/rustc_hir_typeck/src/method/suggest.rs | 12 ++++++++++-- .../mutability-mismatch-arg.fixed | 2 +- .../illegal-sized-bound/mutability-mismatch-arg.rs | 2 +- .../mutability-mismatch-arg.stderr | 5 +---- .../ui/illegal-sized-bound/mutability-mismatch.rs | 6 ++---- .../illegal-sized-bound/mutability-mismatch.stderr | 14 ++++---------- src/test/ui/suggestions/imm-ref-trait-object.rs | 2 +- .../ui/suggestions/imm-ref-trait-object.stderr | 5 +---- 8 files changed, 21 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5a43db69fd49..fedffe3d81ea 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -177,9 +177,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } MethodError::IllegalSizedBound(candidates, needs_mut, bound_span, self_expr) => { - let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); + let msg = if needs_mut { + with_forced_trimmed_paths!(format!( + "the `{item_name}` method cannot be invoked on `{rcvr_ty}`" + )) + } else { + format!("the `{item_name}` method cannot be invoked on a trait object") + }; let mut err = self.sess().struct_span_err(span, &msg); - err.span_label(bound_span, "this has a `Sized` requirement"); + if !needs_mut { + err.span_label(bound_span, "this has a `Sized` requirement"); + } if !candidates.is_empty() { let help = format!( "{an}other candidate{s} {were} found in the following trait{s}, perhaps \ diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed index 260ef5458d4b..74f3c887f027 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.fixed @@ -1,6 +1,6 @@ // run-rustfix fn test(t: &mut dyn Iterator) -> u64 { - *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on } fn main() { diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs index 7a1656507f2c..3b02c5a5ad15 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.rs @@ -1,6 +1,6 @@ // run-rustfix fn test(t: &dyn Iterator) -> u64 { - *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object + *t.min().unwrap() //~ ERROR the `min` method cannot be invoked on } fn main() { diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr index 9b4b9b65d104..89613bd5c202 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch-arg.stderr @@ -1,11 +1,8 @@ -error: the `min` method cannot be invoked on a trait object +error: the `min` method cannot be invoked on `&dyn Iterator` --> $DIR/mutability-mismatch-arg.rs:3:9 | LL | *t.min().unwrap() | ^^^ - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this has a `Sized` requirement | help: you need `&mut dyn Iterator` instead of `&dyn Iterator` | diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs index aa9b3d038914..01bb3537c2dd 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch.rs +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.rs @@ -4,7 +4,6 @@ pub trait MutTrait { fn function(&mut self) where Self: Sized; - //~^ this has a `Sized` requirement } impl MutTrait for MutType { @@ -17,7 +16,6 @@ pub trait Trait { fn function(&self) where Self: Sized; - //~^ this has a `Sized` requirement } impl Trait for Type { @@ -26,9 +24,9 @@ impl Trait for Type { fn main() { (&MutType as &dyn MutTrait).function(); - //~^ ERROR the `function` method cannot be invoked on a trait object + //~^ ERROR the `function` method cannot be invoked on `&dyn MutTrait` //~| HELP you need `&mut dyn MutTrait` instead of `&dyn MutTrait` (&mut Type as &mut dyn Trait).function(); - //~^ ERROR the `function` method cannot be invoked on a trait object + //~^ ERROR the `function` method cannot be invoked on `&mut dyn Trait` //~| HELP you need `&dyn Trait` instead of `&mut dyn Trait` } diff --git a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr index 0120b9f91e94..2ca571d9b792 100644 --- a/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr +++ b/src/test/ui/illegal-sized-bound/mutability-mismatch.stderr @@ -1,20 +1,14 @@ -error: the `function` method cannot be invoked on a trait object - --> $DIR/mutability-mismatch.rs:28:33 +error: the `function` method cannot be invoked on `&dyn MutTrait` + --> $DIR/mutability-mismatch.rs:26:33 | -LL | Self: Sized; - | ----- this has a `Sized` requirement -... LL | (&MutType as &dyn MutTrait).function(); | ^^^^^^^^ | = help: you need `&mut dyn MutTrait` instead of `&dyn MutTrait` -error: the `function` method cannot be invoked on a trait object - --> $DIR/mutability-mismatch.rs:31:35 +error: the `function` method cannot be invoked on `&mut dyn Trait` + --> $DIR/mutability-mismatch.rs:29:35 | -LL | Self: Sized; - | ----- this has a `Sized` requirement -... LL | (&mut Type as &mut dyn Trait).function(); | ^^^^^^^^ | diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs index 288d6c699f59..c1c969b90e4d 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object.rs +++ b/src/test/ui/suggestions/imm-ref-trait-object.rs @@ -1,5 +1,5 @@ fn test(t: &dyn Iterator) -> u64 { - t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object + t.min().unwrap() //~ ERROR the `min` method cannot be invoked on `&dyn Iterator` } fn main() { diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr index 02847ed8c4c6..f7f7902c17d1 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -1,11 +1,8 @@ -error: the `min` method cannot be invoked on a trait object +error: the `min` method cannot be invoked on `&dyn Iterator` --> $DIR/imm-ref-trait-object.rs:2:8 | LL | t.min().unwrap() | ^^^ - --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL - | - = note: this has a `Sized` requirement | help: you need `&mut dyn Iterator` instead of `&dyn Iterator` | From 2631a5df6135b8cf877fa2464fe428a6bc704048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 07:12:04 +0000 Subject: [PATCH 194/223] Turn `IllegalSizedBound` into struct variant --- compiler/rustc_hir_typeck/src/method/mod.rs | 11 ++++++++--- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index f3c43e3f4973..d276bcdb81e3 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -57,7 +57,12 @@ pub enum MethodError<'tcx> { PrivateMatch(DefKind, DefId, Vec), // Found a `Self: Sized` bound where `Self` is a trait object. - IllegalSizedBound(Vec, bool, Span, &'tcx hir::Expr<'tcx>), + IllegalSizedBound { + candidates: Vec, + needs_mut: bool, + bound_span: Span, + self_expr: &'tcx hir::Expr<'tcx>, + }, // Found a match, but the return type is wrong BadReturnType, @@ -112,7 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(NoMatch(..)) => false, Err(Ambiguity(..)) => true, Err(PrivateMatch(..)) => allow_private, - Err(IllegalSizedBound(..)) => true, + Err(IllegalSizedBound { .. }) => true, Err(BadReturnType) => bug!("no return type expectations but got BadReturnType"), } } @@ -236,7 +241,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => Vec::new(), }; - return Err(IllegalSizedBound(candidates, needs_mut, span, self_expr)); + return Err(IllegalSizedBound { candidates, needs_mut, bound_span: span, self_expr }); } Ok(result.callee) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index fedffe3d81ea..bcdb557be217 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - MethodError::IllegalSizedBound(candidates, needs_mut, bound_span, self_expr) => { + MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => { let msg = if needs_mut { with_forced_trimmed_paths!(format!( "the `{item_name}` method cannot be invoked on `{rcvr_ty}`" From b693365b846b13c1da6c5158cc7f4598a1aaa2e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Jan 2023 21:08:56 +0000 Subject: [PATCH 195/223] fix rebase --- compiler/rustc_hir_typeck/src/method/suggest.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index bcdb557be217..536c42706595 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -214,13 +214,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind && let hir::def::Res::Local(hir_id) = path.res - && let Some(hir::Node::Pat(binding)) = self.tcx.hir().find(hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(binding.hir_id) - && let Some(hir::Node::Param(param)) = self.tcx.hir().find(parent_hir_id) - && let parent_hir_id = self.tcx.hir().get_parent_node(param.hir_id) - && let Some(node) = self.tcx.hir().find(parent_hir_id) + && let Some(hir::Node::Pat(b)) = self.tcx.hir().find(hir_id) + && let Some(hir::Node::Param(p)) = self.tcx.hir().find_parent(b.hir_id) + && let Some(node) = self.tcx.hir().find_parent(p.hir_id) && let Some(decl) = node.fn_decl() - && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == param.ty_span) + && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span) && let hir::TyKind::Ref(_, mut_ty) = &ty.kind && let hir::Mutability::Not = mut_ty.mutbl { From d4139b36cf8bdc3c46616112fed42b589dec5395 Mon Sep 17 00:00:00 2001 From: Nixon Enraght-Moony Date: Fri, 6 Jan 2023 23:10:14 +0000 Subject: [PATCH 196/223] jsondoclint: Check local items in `paths` are also in `index`. --- src/tools/jsondoclint/src/validator.rs | 29 +++++- src/tools/jsondoclint/src/validator/tests.rs | 100 ++++++++++++++++++- 2 files changed, 125 insertions(+), 4 deletions(-) diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index f1b9c1acbaec..c6f55410e443 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -3,14 +3,17 @@ use std::hash::Hash; use rustdoc_json_types::{ Constant, Crate, DynTrait, Enum, FnDecl, Function, FunctionPointer, GenericArg, GenericArgs, - GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, Module, OpaqueTy, Path, - Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, Type, TypeBinding, - TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, + GenericBound, GenericParamDef, Generics, Id, Impl, Import, ItemEnum, ItemSummary, Module, + OpaqueTy, Path, Primitive, ProcMacro, Static, Struct, StructKind, Term, Trait, TraitAlias, + Type, TypeBinding, TypeBindingKind, Typedef, Union, Variant, VariantKind, WherePredicate, }; use serde_json::Value; use crate::{item_kind::Kind, json_find, Error, ErrorKind}; +// This is a rustc implementation detail that we rely on here +const LOCAL_CRATE_ID: u32 = 0; + /// The Validator walks over the JSON tree, and ensures it is well formed. /// It is made of several parts. /// @@ -53,12 +56,19 @@ impl<'a> Validator<'a> { } pub fn check_crate(&mut self) { + // Graph traverse the index let root = &self.krate.root; self.add_mod_id(root); while let Some(id) = set_remove(&mut self.todo) { self.seen_ids.insert(id); self.check_item(id); } + + let root_crate_id = self.krate.index[root].crate_id; + assert_eq!(root_crate_id, LOCAL_CRATE_ID, "LOCAL_CRATE_ID is wrong"); + for (id, item_info) in &self.krate.paths { + self.check_item_info(id, item_info); + } } fn check_item(&mut self, id: &'a Id) { @@ -364,6 +374,19 @@ impl<'a> Validator<'a> { fp.generic_params.iter().for_each(|gpd| self.check_generic_param_def(gpd)); } + fn check_item_info(&mut self, id: &Id, item_info: &ItemSummary) { + // FIXME: Their should be a better way to determine if an item is local, rather than relying on `LOCAL_CRATE_ID`, + // which encodes rustc implementation details. + if item_info.crate_id == LOCAL_CRATE_ID && !self.krate.index.contains_key(id) { + self.errs.push(Error { + id: id.clone(), + kind: ErrorKind::Custom( + "Id for local item in `paths` but not in `index`".to_owned(), + ), + }) + } + } + fn add_id_checked(&mut self, id: &'a Id, valid: fn(Kind) -> bool, expected: &str) { if let Some(kind) = self.kind_of(id) { if valid(kind) { diff --git a/src/tools/jsondoclint/src/validator/tests.rs b/src/tools/jsondoclint/src/validator/tests.rs index 37b826153efb..1ef41ff123ab 100644 --- a/src/tools/jsondoclint/src/validator/tests.rs +++ b/src/tools/jsondoclint/src/validator/tests.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use rustdoc_json_types::{Crate, Item, Visibility}; +use rustdoc_json_types::{Crate, Item, ItemKind, ItemSummary, Visibility, FORMAT_VERSION}; use crate::json_find::SelectorPart; @@ -64,3 +64,101 @@ fn errors_on_missing_links() { }], ); } + +// Test we would catch +// https://github.com/rust-lang/rust/issues/104064#issuecomment-1368589718 +#[test] +fn errors_on_local_in_paths_and_not_index() { + let krate = Crate { + root: id("0:0:1572"), + crate_version: None, + includes_private: false, + index: HashMap::from_iter([ + ( + id("0:0:1572"), + Item { + id: id("0:0:1572"), + crate_id: 0, + name: Some("microcore".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::from_iter([(("prim@i32".to_owned(), id("0:1:1571")))]), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Module(Module { + is_crate: true, + items: vec![id("0:1:717")], + is_stripped: false, + }), + }, + ), + ( + id("0:1:717"), + Item { + id: id("0:1:717"), + crate_id: 0, + name: Some("i32".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::default(), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Primitive(Primitive { name: "i32".to_owned(), impls: vec![] }), + }, + ), + ]), + paths: HashMap::from_iter([( + id("0:1:1571"), + ItemSummary { + crate_id: 0, + path: vec!["microcore".to_owned(), "i32".to_owned()], + kind: ItemKind::Primitive, + }, + )]), + external_crates: HashMap::default(), + format_version: rustdoc_json_types::FORMAT_VERSION, + }; + + check( + &krate, + &[Error { + id: id("0:1:1571"), + kind: ErrorKind::Custom("Id for local item in `paths` but not in `index`".to_owned()), + }], + ); +} + +#[test] +#[should_panic = "LOCAL_CRATE_ID is wrong"] +fn checks_local_crate_id_is_correct() { + let krate = Crate { + root: id("root"), + crate_version: None, + includes_private: false, + index: HashMap::from_iter([( + id("root"), + Item { + id: id("root"), + crate_id: LOCAL_CRATE_ID.wrapping_add(1), + name: Some("irrelavent".to_owned()), + span: None, + visibility: Visibility::Public, + docs: None, + links: HashMap::default(), + attrs: Vec::new(), + deprecation: None, + inner: ItemEnum::Module(Module { + is_crate: true, + items: vec![], + is_stripped: false, + }), + }, + )]), + paths: HashMap::default(), + external_crates: HashMap::default(), + format_version: FORMAT_VERSION, + }; + check(&krate, &[]); +} From 6082729646e3530ecdd522921837806db83b27e3 Mon Sep 17 00:00:00 2001 From: yukang Date: Sat, 7 Jan 2023 07:16:48 +0800 Subject: [PATCH 197/223] use type_implements_trait to check Param clone --- .../src/traits/error_reporting/suggestions.rs | 27 +++++-------------- .../issue-106443-sugg-clone-for-bound.rs | 4 +-- 2 files changed, 9 insertions(+), 22 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 727bdc391bb4..c52365ae3b7c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1121,36 +1121,23 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let Some(generics) = self.tcx.hir().get_generics(owner.def_id) else { return false }; let ty::Ref(_, inner_ty, hir::Mutability::Not) = ty.kind() else { return false }; let ty::Param(param) = inner_ty.kind() else { return false }; - let Some(generic_param) = generics.get_named(param.name) else { return false }; let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code() else { return false }; let arg_node = self.tcx.hir().get(*arg_hir_id); let Node::Expr(Expr { kind: hir::ExprKind::Path(_), ..}) = arg_node else { return false }; let clone_trait = self.tcx.require_lang_item(LangItem::Clone, None); - let has_clone = self - .type_implements_trait(clone_trait, [ty], obligation.param_env) - .must_apply_modulo_regions(); + let has_clone = |ty| { + self.type_implements_trait(clone_trait, [ty], obligation.param_env) + .must_apply_modulo_regions() + }; - let trait_pred_and_suggested_ty = - trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)); let new_obligation = self.mk_trait_obligation_with_new_self_ty( obligation.param_env, - trait_pred_and_suggested_ty, + trait_pred.map_bound(|trait_pred| (trait_pred, *inner_ty)), ); - if has_clone && self.predicate_may_hold(&new_obligation) { - let clone_bound = generics - .bounds_for_param(generic_param.def_id) - .flat_map(|bp| bp.bounds) - .any(|bound| { - if let hir::GenericBound::Trait(hir::PolyTraitRef { trait_ref, .. }, ..) = bound - { - Some(clone_trait) == trait_ref.trait_def_id() - } else { - false - } - }); - if !clone_bound { + if self.predicate_may_hold(&new_obligation) && has_clone(ty) { + if !has_clone(param.to_ty(self.tcx)) { suggest_constraining_type_param( self.tcx, generics, diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs index 4e4d4c044c98..3b2e316b2961 100644 --- a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.rs @@ -6,11 +6,11 @@ trait X {} impl X for S {} fn foo(_: T) {} -fn bar(s: &T) { +fn bar(s: &T) { foo(s); //~ ERROR the trait bound `&T: X` is not satisfied } -fn bar_with_clone(s: &T) { +fn bar_with_clone(s: &T) { foo(s); //~ ERROR the trait bound `&T: X` is not satisfied } From 43bec832667252ea2e78abe17918ba5fbbc1e27d Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 7 Jan 2023 17:08:04 +1300 Subject: [PATCH 198/223] docs: make `HashSet::retain` doctest more clear --- library/std/src/collections/hash/set.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index cee884145c71..b59f89d321c4 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -317,7 +317,7 @@ impl HashSet { /// /// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]); /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); + /// assert_eq!(set, HashSet::from([2, 4, 6])); /// ``` /// /// # Performance From dc0e4207d4d621d031ef25395f93cc43d36a08f2 Mon Sep 17 00:00:00 2001 From: LingMan Date: Sat, 7 Jan 2023 05:10:53 +0100 Subject: [PATCH 199/223] Fix a typo in the explanation of E0588 --- compiler/rustc_error_codes/src/error_codes/E0588.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0588.md b/compiler/rustc_error_codes/src/error_codes/E0588.md index 040c7a02ef4d..995d945f1589 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0588.md +++ b/compiler/rustc_error_codes/src/error_codes/E0588.md @@ -11,7 +11,7 @@ struct Aligned(i32); struct Packed(Aligned); ``` -Just like you cannot have both `align` and `packed` representation hints on a +Just like you cannot have both `align` and `packed` representation hints on the same type, a `packed` type cannot contain another type with the `align` representation hint. However, you can do the opposite: From a7ac923088e6088be6c16c27dd9dca07bad7a391 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 6 Jan 2023 22:21:54 -0700 Subject: [PATCH 200/223] rustdoc: remove no-op mobile CSS `.content { margin-left: 0 }` This rule was added to override non-zero left margin on `.content`, which was removed in 135281ed1525db15edd8ebd092aa10aa40df2386 and the margin-left was put on the docblock. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 05a12d3d4d4a..c1ed0ccef886 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1655,10 +1655,6 @@ in storage.js margin-top: 1em; } - .content { - margin-left: 0px; - } - .anchor { display: none !important; } From 09382db78b293a649115fbd3d5bc79aaaf7b8deb Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 7 Jan 2023 18:36:32 +1300 Subject: [PATCH 201/223] minor fixes for `error_codes.rs` tidy check --- src/tools/tidy/src/error_codes.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index fdc9d7899059..4b0a62fac839 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -15,8 +15,6 @@ //! //! 4. We check that the error code is actually emitted by the compiler. //! - This is done by searching `compiler/` with a regex. -//! -//! This tidy check was merged and refactored from two others. See #PR_NUM for information about linting changes that occurred during this refactor. use std::{ffi::OsStr, fs, path::Path}; @@ -57,7 +55,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut let no_longer_emitted = check_error_codes_docs(root_path, &error_codes, &mut errors, verbose); // Stage 3: check list has UI tests - check_error_codes_tests(root_path, &error_codes, &mut errors, verbose); + check_error_codes_tests(root_path, &error_codes, &mut errors, verbose, &no_longer_emitted); // Stage 4: check list is emitted by compiler check_error_codes_used(search_paths, &error_codes, &mut errors, &no_longer_emitted, verbose); @@ -174,8 +172,9 @@ fn check_error_codes_docs( return; } - let (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) = + let (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) = check_explanation_has_doctest(&contents, &err_code); + if emit_ignore_warning { verbose_print!( verbose, @@ -183,13 +182,11 @@ fn check_error_codes_docs( `IGNORE_DOCTEST_CHECK` constant instead." ); } - if emit_no_longer_warning { + + if no_longer_emitted { no_longer_emitted_codes.push(err_code.to_owned()); - verbose_print!( - verbose, - "warning: Error code `{err_code}` is no longer emitted and should be removed entirely." - ); } + if !found_code_example { verbose_print!( verbose, @@ -226,7 +223,7 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo let mut found_proper_doctest = false; let mut emit_ignore_warning = false; - let mut emit_no_longer_warning = false; + let mut no_longer_emitted = false; for line in explanation.lines() { let line = line.trim(); @@ -246,13 +243,13 @@ fn check_explanation_has_doctest(explanation: &str, err_code: &str) -> (bool, bo } else if line .starts_with("#### Note: this error code is no longer emitted by the compiler") { - emit_no_longer_warning = true; + no_longer_emitted = true; found_code_example = true; found_proper_doctest = true; } } - (found_code_example, found_proper_doctest, emit_ignore_warning, emit_no_longer_warning) + (found_code_example, found_proper_doctest, emit_ignore_warning, no_longer_emitted) } // Stage 3: Checks that each error code has a UI test in the correct directory @@ -261,6 +258,7 @@ fn check_error_codes_tests( error_codes: &[String], errors: &mut Vec, verbose: bool, + no_longer_emitted: &[String], ) { let tests_path = root_path.join(Path::new(ERROR_TESTS_PATH)); @@ -295,6 +293,11 @@ fn check_error_codes_tests( } }; + if no_longer_emitted.contains(code) { + // UI tests *can't* contain error codes that are no longer emitted. + continue; + } + let mut found_code = false; for line in file.lines() { From 75f1dfcc3236029bbd33799b94742424711e0376 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 22 Dec 2022 20:18:30 +0900 Subject: [PATCH 202/223] Add regression test for #86106 Signed-off-by: Yuki Okushi --- src/test/codegen/issue-86106.rs | 56 +++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/test/codegen/issue-86106.rs diff --git a/src/test/codegen/issue-86106.rs b/src/test/codegen/issue-86106.rs new file mode 100644 index 000000000000..e81cab9f1df7 --- /dev/null +++ b/src/test/codegen/issue-86106.rs @@ -0,0 +1,56 @@ +// min-llvm-version: 15.0 +// compile-flags: -C opt-level=3 -C target-cpu=native + +// The below two functions ensure that both `String::new()` and `"".to_string()` +// produce the identical code. + +#![crate_type = "lib"] + +// CHECK-LABEL: @string_new = unnamed_addr alias void (ptr), ptr @empty_to_string +// CHECK: define void @empty_to_string +#[no_mangle] +pub fn string_new() -> String { + String::new() +} + +#[no_mangle] +pub fn empty_to_string() -> String { + // CHECK-NOT: load i8 + // CHECK: store i64 + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store ptr + // CHECK-NEXT: getelementptr + // CHECK-NOT: store i8 + // CHECK-NEXT: store i64 + // CHECK-NEXT: ret void + "".to_string() +} + +// The below two functions ensure that both `vec![]` and `vec![].clone()` +// produce the identical code. + +// CHECK-LABEL: @empty_vec +#[no_mangle] +pub fn empty_vec() -> Vec { + // CHECK: store i64 + // CHECK-NOT: load i8 + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store ptr + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store i64 + // CHECK-NEXT: ret void + vec![] +} + +// CHECK-LABEL: @empty_vec_clone +#[no_mangle] +pub fn empty_vec_clone() -> Vec { + // CHECK: store i64 + // CHECK-NOT: load i8 + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store ptr + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store i64 + // CHECK-NEXT: ret void + vec![].clone() +} From 78e11a45564e1e8a67f0078fe89659032aed41a6 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 22 Dec 2022 20:45:36 +0900 Subject: [PATCH 203/223] Apply review suggestions Signed-off-by: Yuki Okushi --- src/test/codegen/issue-86106.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/test/codegen/issue-86106.rs b/src/test/codegen/issue-86106.rs index e81cab9f1df7..e647dbe2514d 100644 --- a/src/test/codegen/issue-86106.rs +++ b/src/test/codegen/issue-86106.rs @@ -1,5 +1,5 @@ // min-llvm-version: 15.0 -// compile-flags: -C opt-level=3 -C target-cpu=native +// compile-flags: -C opt-level=3 // The below two functions ensure that both `String::new()` and `"".to_string()` // produce the identical code. @@ -7,21 +7,20 @@ #![crate_type = "lib"] // CHECK-LABEL: @string_new = unnamed_addr alias void (ptr), ptr @empty_to_string -// CHECK: define void @empty_to_string #[no_mangle] pub fn string_new() -> String { String::new() } +// CHECK-LABEL: define void @empty_to_string #[no_mangle] pub fn empty_to_string() -> String { // CHECK-NOT: load i8 - // CHECK: store i64 + // CHECK: store i{{32|64}} // CHECK-NEXT: getelementptr // CHECK-NEXT: store ptr // CHECK-NEXT: getelementptr - // CHECK-NOT: store i8 - // CHECK-NEXT: store i64 + // CHECK-NEXT: store i{{32|64}} // CHECK-NEXT: ret void "".to_string() } @@ -32,12 +31,12 @@ pub fn empty_to_string() -> String { // CHECK-LABEL: @empty_vec #[no_mangle] pub fn empty_vec() -> Vec { - // CHECK: store i64 + // CHECK: store i{{32|64}} // CHECK-NOT: load i8 // CHECK-NEXT: getelementptr // CHECK-NEXT: store ptr // CHECK-NEXT: getelementptr - // CHECK-NEXT: store i64 + // CHECK-NEXT: store i{{32|64}} // CHECK-NEXT: ret void vec![] } @@ -45,12 +44,12 @@ pub fn empty_vec() -> Vec { // CHECK-LABEL: @empty_vec_clone #[no_mangle] pub fn empty_vec_clone() -> Vec { - // CHECK: store i64 + // CHECK: store i{{32|64}} // CHECK-NOT: load i8 // CHECK-NEXT: getelementptr // CHECK-NEXT: store ptr // CHECK-NEXT: getelementptr - // CHECK-NEXT: store i64 + // CHECK-NEXT: store i{{32|64}} // CHECK-NEXT: ret void vec![].clone() } From ab9313e624d581a75f4b886c0adf351f848d725a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 Jan 2023 19:03:07 +0900 Subject: [PATCH 204/223] Apply `merge-functions=disabled` Signed-off-by: Yuki Okushi --- src/test/codegen/issue-86106.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/test/codegen/issue-86106.rs b/src/test/codegen/issue-86106.rs index e647dbe2514d..9ccbcb24f562 100644 --- a/src/test/codegen/issue-86106.rs +++ b/src/test/codegen/issue-86106.rs @@ -1,14 +1,21 @@ // min-llvm-version: 15.0 -// compile-flags: -C opt-level=3 +// compile-flags: -C opt-level=3 -Z merge-functions=disabled // The below two functions ensure that both `String::new()` and `"".to_string()` // produce the identical code. #![crate_type = "lib"] -// CHECK-LABEL: @string_new = unnamed_addr alias void (ptr), ptr @empty_to_string +// CHECK-LABEL: define void @string_new #[no_mangle] pub fn string_new() -> String { + // CHECK-NOT: load i8 + // CHECK: store i{{32|64}} + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store ptr + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store i{{32|64}} + // CHECK-NEXT: ret void String::new() } From fed349957dc774b4f5f614e030fe61304e9325f8 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Sat, 7 Jan 2023 14:38:21 +0000 Subject: [PATCH 205/223] Clarify examples for `VecDeque::get/get_mut` --- library/alloc/src/collections/vec_deque/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c955db46d29f..1b576521a91d 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -636,6 +636,7 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); + /// buf.push_back(6); /// assert_eq!(buf.get(1), Some(&4)); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -661,10 +662,11 @@ impl VecDeque { /// buf.push_back(3); /// buf.push_back(4); /// buf.push_back(5); + /// buf.push_back(6); + /// assert_eq!(buf[1], 4); /// if let Some(elem) = buf.get_mut(1) { /// *elem = 7; /// } - /// /// assert_eq!(buf[1], 7); /// ``` #[stable(feature = "rust1", since = "1.0.0")] From a139fd06277dd714b5244fcbb621488e1da2d518 Mon Sep 17 00:00:00 2001 From: Folyd Date: Sat, 7 Jan 2023 23:50:07 +0800 Subject: [PATCH 206/223] Change to immutable borrow when cloning element of RepeatN --- library/core/src/iter/sources/repeat_n.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index fd8d25ce1a55..dc61d6065b8e 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -126,7 +126,7 @@ impl Iterator for RepeatN { // zero so it won't be dropped later, and thus it's okay to take it here. unsafe { ManuallyDrop::take(&mut self.element) } } else { - A::clone(&mut self.element) + A::clone(&self.element) }) } From eddb479ad36841a858f186af81d4ac360d2a2058 Mon Sep 17 00:00:00 2001 From: Sky Date: Sat, 7 Jan 2023 14:16:59 -0500 Subject: [PATCH 207/223] Don't derive Debug for `OnceWith` & `RepeatWith` --- library/core/src/iter/sources/once_with.rs | 14 +++++++++++++- library/core/src/iter/sources/repeat_with.rs | 10 +++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/sources/once_with.rs b/library/core/src/iter/sources/once_with.rs index d79f85c2559f..080ae27a30fc 100644 --- a/library/core/src/iter/sources/once_with.rs +++ b/library/core/src/iter/sources/once_with.rs @@ -1,3 +1,4 @@ +use crate::fmt; use crate::iter::{FusedIterator, TrustedLen}; /// Creates an iterator that lazily generates a value exactly once by invoking @@ -66,12 +67,23 @@ pub fn once_with A>(gen: F) -> OnceWith { /// /// This `struct` is created by the [`once_with()`] function. /// See its documentation for more. -#[derive(Clone, Debug)] +#[derive(Clone)] #[stable(feature = "iter_once_with", since = "1.43.0")] pub struct OnceWith { gen: Option, } +#[stable(feature = "iter_once_with_debug", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for OnceWith { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.gen.is_some() { + f.write_str("OnceWith(Some(_))") + } else { + f.write_str("OnceWith(None)") + } + } +} + #[stable(feature = "iter_once_with", since = "1.43.0")] impl A> Iterator for OnceWith { type Item = A; diff --git a/library/core/src/iter/sources/repeat_with.rs b/library/core/src/iter/sources/repeat_with.rs index ab2d0472b470..20420a3ad8e0 100644 --- a/library/core/src/iter/sources/repeat_with.rs +++ b/library/core/src/iter/sources/repeat_with.rs @@ -1,3 +1,4 @@ +use crate::fmt; use crate::iter::{FusedIterator, TrustedLen}; use crate::ops::Try; @@ -71,12 +72,19 @@ pub fn repeat_with A>(repeater: F) -> RepeatWith { /// /// This `struct` is created by the [`repeat_with()`] function. /// See its documentation for more. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone)] #[stable(feature = "iterator_repeat_with", since = "1.28.0")] pub struct RepeatWith { repeater: F, } +#[stable(feature = "iterator_repeat_with_debug", since = "CURRENT_RUSTC_VERSION")] +impl fmt::Debug for RepeatWith { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RepeatWith").finish_non_exhaustive() + } +} + #[stable(feature = "iterator_repeat_with", since = "1.28.0")] impl A> Iterator for RepeatWith { type Item = A; From 288e89bf76856653b69c8db77003ab190e86272b Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sat, 7 Jan 2023 15:56:36 -0800 Subject: [PATCH 208/223] Document that `Vec::from_raw_parts[_in]` must be given a pointer from the correct allocator. --- library/alloc/src/vec/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 1da73862d4a9..36cfac8ee9e1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -490,6 +490,8 @@ impl Vec { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// + /// * `ptr` must have been allocated using the global allocator, such as via + /// the [`alloc::alloc`] function. /// * `T` needs to have the same alignment as what `ptr` was allocated with. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be @@ -526,6 +528,7 @@ impl Vec { /// function. /// /// [`String`]: crate::string::String + /// [`alloc::alloc`]: crate::alloc::alloc /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc /// /// # Examples @@ -681,6 +684,7 @@ impl Vec { /// This is highly unsafe, due to the number of invariants that aren't /// checked: /// + /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. /// * `T` needs to have the same alignment as what `ptr` was allocated with. /// (`T` having a less strict alignment is not sufficient, the alignment really /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be @@ -714,6 +718,7 @@ impl Vec { /// /// [`String`]: crate::string::String /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory /// [*fit*]: crate::alloc::Allocator#memory-fitting /// /// # Examples From ae61c250cd6124d0ec5095acb3be64b633268ab3 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 7 Jan 2023 18:37:40 +1300 Subject: [PATCH 209/223] doc/test: add UI test and reword docs for `E0013` and `E0015` --- .../src/error_codes/E0015.md | 23 +++++++------------ src/test/ui/error-codes/E0013.rs | 4 ++++ src/test/ui/error-codes/E0013.stderr | 11 +++++++++ src/test/ui/error-codes/E0015.rs | 8 +++++++ src/test/ui/error-codes/E0015.stderr | 11 +++++++++ 5 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/error-codes/E0013.rs create mode 100644 src/test/ui/error-codes/E0013.stderr create mode 100644 src/test/ui/error-codes/E0015.rs create mode 100644 src/test/ui/error-codes/E0015.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0015.md b/compiler/rustc_error_codes/src/error_codes/E0015.md index 021a0219d13e..ac78f66adada 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0015.md +++ b/compiler/rustc_error_codes/src/error_codes/E0015.md @@ -1,5 +1,4 @@ -A constant item was initialized with something that is not a constant -expression. +A non-`const` function was called in a `const` context. Erroneous code example: @@ -8,26 +7,20 @@ fn create_some() -> Option { Some(1) } -const FOO: Option = create_some(); // error! +// error: cannot call non-const fn `create_some` in constants +const FOO: Option = create_some(); ``` -The only functions that can be called in static or constant expressions are -`const` functions, and struct/enum constructors. +All functions used in a `const` context (constant or static expression) must +be marked `const`. To fix this error, you can declare `create_some` as a constant function: ``` -const fn create_some() -> Option { // declared as a const function +// declared as a `const` function: +const fn create_some() -> Option { Some(1) } -const FOO: Option = create_some(); // ok! - -// These are also working: -struct Bar { - x: u8, -} - -const OTHER_FOO: Option = Some(1); -const BAR: Bar = Bar {x: 1}; +const FOO: Option = create_some(); // no error! ``` diff --git a/src/test/ui/error-codes/E0013.rs b/src/test/ui/error-codes/E0013.rs new file mode 100644 index 000000000000..9b3982a785b7 --- /dev/null +++ b/src/test/ui/error-codes/E0013.rs @@ -0,0 +1,4 @@ +static X: i32 = 42; +const Y: i32 = X; //~ ERROR constants cannot refer to statics [E0013] + +fn main() {} diff --git a/src/test/ui/error-codes/E0013.stderr b/src/test/ui/error-codes/E0013.stderr new file mode 100644 index 000000000000..dc22053a6389 --- /dev/null +++ b/src/test/ui/error-codes/E0013.stderr @@ -0,0 +1,11 @@ +error[E0013]: constants cannot refer to statics + --> $DIR/E0013.rs:2:16 + | +LL | const Y: i32 = X; + | ^ + | + = help: consider extracting the value of the `static` to a `const`, and referring to that + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0013`. diff --git a/src/test/ui/error-codes/E0015.rs b/src/test/ui/error-codes/E0015.rs new file mode 100644 index 000000000000..b0211358d816 --- /dev/null +++ b/src/test/ui/error-codes/E0015.rs @@ -0,0 +1,8 @@ +fn create_some() -> Option { + Some(1) +} + +const FOO: Option = create_some(); +//~^ ERROR cannot call non-const fn `create_some` in constants [E0015] + +fn main() {} diff --git a/src/test/ui/error-codes/E0015.stderr b/src/test/ui/error-codes/E0015.stderr new file mode 100644 index 000000000000..ec1ce47b2ce7 --- /dev/null +++ b/src/test/ui/error-codes/E0015.stderr @@ -0,0 +1,11 @@ +error[E0015]: cannot call non-const fn `create_some` in constants + --> $DIR/E0015.rs:5:25 + | +LL | const FOO: Option = create_some(); + | ^^^^^^^^^^^^^ + | + = note: calls in constants are limited to constant functions, tuple structs and tuple variants + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. From 93c0d8d5d59e096dc2ed545d1eba09f16f0b5874 Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sun, 8 Jan 2023 14:46:01 +1300 Subject: [PATCH 210/223] remove unreachable error code `E0313` --- compiler/rustc_error_codes/src/error_codes.rs | 3 +- .../src/infer/error_reporting/mod.rs | 1 - .../src/infer/error_reporting/note.rs | 37 ------------------- compiler/rustc_infer/src/infer/mod.rs | 4 -- src/tools/tidy/src/error_codes.rs | 4 +- 5 files changed, 3 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs index 3fba2cf57494..76d5da19399e 100644 --- a/compiler/rustc_error_codes/src/error_codes.rs +++ b/compiler/rustc_error_codes/src/error_codes.rs @@ -579,8 +579,7 @@ E0791: include_str!("./error_codes/E0791.md"), // E0300, // unexpanded macro // E0304, // expected signed integer constant // E0305, // expected constant - E0313, // lifetime of borrowed pointer outlives lifetime of captured - // variable +// E0313, // removed: found unreachable // E0314, // closure outlives stack frame // E0315, // cannot invoke closure outside of its lifetime // E0319, // trait impls for defaulted traits allowed just for structs/enums diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0644c7ada10f..b02e7d73c51f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1,4 +1,3 @@ -// ignore-tidy-filelength //! Error Reporting Code for the inference engine //! //! Because of the way inference, and in particular region inference, diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index d91ef882bc4b..7bb79d7bda8d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -25,16 +25,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { infer::Reborrow(span) => { RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err) } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - RegionOriginNote::WithName { - span, - msg: fluent::infer_reborrow, - name: &var_name.to_string(), - continues: false, - } - .add_to_diagnostic(err); - } infer::RelateObjectBound(span) => { RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound } .add_to_diagnostic(err); @@ -162,33 +152,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); err } - infer::ReborrowUpvar(span, ref upvar_id) => { - let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0313, - "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...", - var_name - ); - note_and_explain_region( - self.tcx, - &mut err, - "...the borrowed pointer is valid for ", - sub, - "...", - None, - ); - note_and_explain_region( - self.tcx, - &mut err, - &format!("...but `{}` is only valid for ", var_name), - sup, - "", - None, - ); - err - } infer::RelateObjectBound(span) => { let mut err = struct_span_err!( self.tcx.sess, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b17a465eb383..bc8bbd4be6ae 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -409,9 +409,6 @@ pub enum SubregionOrigin<'tcx> { /// Creating a pointer `b` to contents of another reference Reborrow(Span), - /// Creating a pointer `b` to contents of an upvar - ReborrowUpvar(Span, ty::UpvarId), - /// Data with type `Ty<'tcx>` was borrowed DataBorrowed(Ty<'tcx>, Span), @@ -1954,7 +1951,6 @@ impl<'tcx> SubregionOrigin<'tcx> { RelateParamBound(a, ..) => a, RelateRegionParamBound(a) => a, Reborrow(a) => a, - ReborrowUpvar(a, _) => a, DataBorrowed(_, a) => a, ReferenceOutlivesReferent(_, a) => a, CompareImplItemObligation { span, .. } => span, diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs index fdc9d7899059..adc074467416 100644 --- a/src/tools/tidy/src/error_codes.rs +++ b/src/tools/tidy/src/error_codes.rs @@ -33,8 +33,8 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602"]; // Error codes that don't yet have a UI test. This list will eventually be removed. const IGNORE_UI_TEST_CHECK: &[&str] = &[ - "E0313", "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", - "E0729", "E0789", + "E0461", "E0465", "E0476", "E0490", "E0514", "E0523", "E0554", "E0640", "E0717", "E0729", + "E0789", ]; macro_rules! verbose_print { From d85d38b7b8ad9faa12231bbcc9a0214410c0719c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2023 01:53:08 +0000 Subject: [PATCH 211/223] Add test --- .../ui/type/closure-with-wrong-borrows.rs | 10 ++++++++ .../ui/type/closure-with-wrong-borrows.stderr | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/test/ui/type/closure-with-wrong-borrows.rs create mode 100644 src/test/ui/type/closure-with-wrong-borrows.stderr diff --git a/src/test/ui/type/closure-with-wrong-borrows.rs b/src/test/ui/type/closure-with-wrong-borrows.rs new file mode 100644 index 000000000000..5f6a78351a24 --- /dev/null +++ b/src/test/ui/type/closure-with-wrong-borrows.rs @@ -0,0 +1,10 @@ +struct S<'a>(&'a str); + +fn f(inner: fn(&str, &S)) { +} + +#[allow(unreachable_code)] +fn main() { + let inner: fn(_, _) = unimplemented!(); + f(inner); //~ ERROR mismatched types +} diff --git a/src/test/ui/type/closure-with-wrong-borrows.stderr b/src/test/ui/type/closure-with-wrong-borrows.stderr new file mode 100644 index 000000000000..e13db6c325ad --- /dev/null +++ b/src/test/ui/type/closure-with-wrong-borrows.stderr @@ -0,0 +1,23 @@ +error[E0308]: mismatched types + --> $DIR/closure-with-wrong-borrows.rs:9:7 + | +LL | f(inner); + | - ^^^^^ one type is more general than the other + | | + | arguments to this function are incorrect + | + = note: expected fn pointer `for<'a, 'b, 'c> fn(&'a str, &'b S<'c>)` + found fn pointer `fn(_, _)` +note: function defined here + --> $DIR/closure-with-wrong-borrows.rs:3:4 + | +LL | fn f(inner: fn(&str, &S)) { + | ^ ------------------- +help: consider removing the `` + | +LL | f(inner); + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From ebbc5dafd351551bdeab3e4edbdf9a03898a9017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 8 Jan 2023 01:53:39 +0000 Subject: [PATCH 212/223] Do not emit wrong E0308 suggestion for closure mismatch --- compiler/rustc_hir_typeck/src/demand.rs | 5 ++++- src/test/ui/type/closure-with-wrong-borrows.stderr | 4 ---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 0f191c21a0a6..f15cf5e3ef94 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1379,7 +1379,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } // If we've reached our target type with just removing `&`, then just print now. - if steps == 0 { + if steps == 0 && !remove.trim().is_empty() { return Some(( prefix_span, format!("consider removing the `{}`", remove.trim()), @@ -1438,6 +1438,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (prefix_span, format!("{}{}", prefix, "*".repeat(steps))) }; + if suggestion.trim().is_empty() { + return None; + } return Some(( span, diff --git a/src/test/ui/type/closure-with-wrong-borrows.stderr b/src/test/ui/type/closure-with-wrong-borrows.stderr index e13db6c325ad..7370bc764676 100644 --- a/src/test/ui/type/closure-with-wrong-borrows.stderr +++ b/src/test/ui/type/closure-with-wrong-borrows.stderr @@ -13,10 +13,6 @@ note: function defined here | LL | fn f(inner: fn(&str, &S)) { | ^ ------------------- -help: consider removing the `` - | -LL | f(inner); - | error: aborting due to previous error From 3c41003873ed16dc415b18ee65602438be3fe1e4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 15 Dec 2022 02:38:39 +0000 Subject: [PATCH 213/223] Add type flags support for Ty and Const late-bound regions --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_middle/src/ty/erase_regions.rs | 2 +- compiler/rustc_middle/src/ty/flags.rs | 16 +++++++++++++-- compiler/rustc_middle/src/ty/visit.rs | 8 ++++++++ compiler/rustc_symbol_mangling/src/v0.rs | 1 + .../src/traits/select/mod.rs | 7 +++---- compiler/rustc_type_ir/src/lib.rs | 20 +++++++++++++------ 7 files changed, 42 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0d1aa39c5d95..1afe62424037 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1912,7 +1912,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { } let pred = obligation.predicate; // Match the existing behavior. - if pred.is_global() && !pred.has_late_bound_regions() { + if pred.is_global() && !pred.has_late_bound_vars() { let pred = self.normalize(span, None, pred); let hir_node = tcx.hir().find(self.body_id); diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index ffdac93bcd09..9e4f90caab0b 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -21,7 +21,7 @@ impl<'tcx> TyCtxt<'tcx> { T: TypeFoldable<'tcx>, { // If there's nothing to erase avoid performing the query at all - if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { + if !value.has_type_flags(TypeFlags::HAS_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) { return value; } debug!("erase_regions({:?})", value); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 8306d670a65d..b7eafc4b4373 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -59,8 +59,18 @@ impl FlagComputation { { let mut computation = FlagComputation::new(); - if !value.bound_vars().is_empty() { - computation.flags = computation.flags | TypeFlags::HAS_RE_LATE_BOUND; + for bv in value.bound_vars() { + match bv { + ty::BoundVariableKind::Ty(_) => { + computation.flags |= TypeFlags::HAS_TY_LATE_BOUND; + } + ty::BoundVariableKind::Region(_) => { + computation.flags |= TypeFlags::HAS_RE_LATE_BOUND; + } + ty::BoundVariableKind::Const => { + computation.flags |= TypeFlags::HAS_CT_LATE_BOUND; + } + } } f(&mut computation, value.skip_binder()); @@ -131,6 +141,7 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_TY_LATE_BOUND); } &ty::Placeholder(..) => { @@ -303,6 +314,7 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => { self.add_bound_var(debruijn); + self.add_flags(TypeFlags::HAS_CT_LATE_BOUND); } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index d5553f84f751..ca4455581313 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -165,6 +165,14 @@ pub trait TypeVisitable<'tcx>: fmt::Debug + Clone { fn has_late_bound_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) } + /// True if there are any late-bound non-region variables + fn has_non_region_late_bound(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND - TypeFlags::HAS_RE_LATE_BOUND) + } + /// True if there are any late-bound variables + fn has_late_bound_vars(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_LATE_BOUND) + } /// Indicates whether this value still has parameters/placeholders/inference variables /// which could be replaced later, in a way that would change the results of `impl` diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 9e8117c6a853..0d446d654dc5 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -206,6 +206,7 @@ impl<'tcx> SymbolMangler<'tcx> { where T: TypeVisitable<'tcx>, { + // FIXME(non-lifetime-binders): What to do here? let regions = if value.has_late_bound_regions() { self.tcx.collect_referenced_late_bound_regions(value) } else { diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 760b4585f4e1..3f14491f8032 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -755,7 +755,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // contain the "'static" lifetime (any other lifetime // would either be late-bound or local), so it is guaranteed // to outlive any other lifetime - if pred.0.is_global() && !pred.0.has_late_bound_regions() { + if pred.0.is_global() && !pred.0.has_late_bound_vars() { Ok(EvaluatedToOk) } else { Ok(EvaluatedToOkModuloRegions) @@ -1785,9 +1785,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Check if a bound would previously have been removed when normalizing // the param_env so that it can be given the lowest priority. See // #50825 for the motivation for this. - let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| { - cand.is_global() && !cand.has_late_bound_regions() - }; + let is_global = + |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars(); // (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`, // `DiscriminantKindCandidate`, `ConstDestructCandidate` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index fed070408f39..44004cb0be1e 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -241,22 +241,30 @@ bitflags! { /// Basically anything but `ReLateBound` and `ReErased`. const HAS_FREE_REGIONS = 1 << 14; - /// Does this have any `ReLateBound` regions? Used to check - /// if a global bound is safe to evaluate. + /// Does this have any `ReLateBound` regions? const HAS_RE_LATE_BOUND = 1 << 15; + /// Does this have any `Bound` types? + const HAS_TY_LATE_BOUND = 1 << 16; + /// Does this have any `ConstKind::Bound` consts? + const HAS_CT_LATE_BOUND = 1 << 17; + /// Does this have any bound variables? + /// Used to check if a global bound is safe to evaluate. + const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits + | TypeFlags::HAS_TY_LATE_BOUND.bits + | TypeFlags::HAS_CT_LATE_BOUND.bits; /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 16; + const HAS_RE_ERASED = 1 << 18; /// Does this value have parameters/placeholders/inference variables which could be /// replaced later, in a way that would change the results of `impl` specialization? - const STILL_FURTHER_SPECIALIZABLE = 1 << 17; + const STILL_FURTHER_SPECIALIZABLE = 1 << 19; /// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`? - const HAS_TY_FRESH = 1 << 18; + const HAS_TY_FRESH = 1 << 20; /// Does this value have `InferConst::Fresh`? - const HAS_CT_FRESH = 1 << 19; + const HAS_CT_FRESH = 1 << 21; } } From 49f849a3d26059cfd89b96a7be7f3bf6ad3058de Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 24 Dec 2022 23:17:25 +0000 Subject: [PATCH 214/223] Mention signature rather than fn pointers when comparing impl/trait methods --- .../locales/en-US/infer.ftl | 4 +-- .../src/check/compare_impl_item.rs | 36 ++++++++----------- compiler/rustc_infer/src/infer/at.rs | 12 +++++++ .../src/infer/error_reporting/mod.rs | 20 +++++++++-- .../trait_impl_difference.rs | 34 ++++++++++-------- compiler/rustc_infer/src/infer/mod.rs | 1 + .../defaults-specialization.stderr | 8 ++--- ...nc-example-desugared-boxed-in-trait.stderr | 4 +-- ...regions-bound-missing-bound-in-impl.stderr | 8 ++--- .../ui/compare-method/bad-self-type.stderr | 12 +++---- src/test/ui/compare-method/issue-90444.stderr | 8 ++--- .../reordered-type-param.stderr | 4 +-- .../impl-generic-mismatch-ab.stderr | 4 +-- .../in-trait/method-signature-matches.stderr | 12 +++---- .../in-trait/signature-mismatch.stderr | 4 +-- .../in-trait/specialization-broken.stderr | 4 +-- ...s-impl-trait-declaration-too-subtle.stderr | 8 ++--- src/test/ui/impl-trait/trait_type.stderr | 4 +-- src/test/ui/issues/issue-13033.rs | 4 +-- src/test/ui/issues/issue-13033.stderr | 4 +-- src/test/ui/issues/issue-15094.rs | 4 +-- src/test/ui/issues/issue-15094.stderr | 4 +-- src/test/ui/issues/issue-20225.stderr | 12 +++---- src/test/ui/issues/issue-21332.stderr | 4 +-- src/test/ui/issues/issue-37884.stderr | 4 +-- ...ime-mismatch-between-trait-and-impl.stderr | 4 +-- src/test/ui/mismatched_types/E0053.stderr | 8 ++--- .../issue-74918-missing-lifetime.stderr | 4 +-- .../issue-75361-mismatched-impl.stderr | 4 +-- .../trait-impl-fn-incompatibility.stderr | 8 ++--- src/test/ui/traits/impl-method-mismatch.rs | 4 +-- .../ui/traits/impl-method-mismatch.stderr | 4 +-- src/test/ui/traits/issue-35869.stderr | 16 ++++----- src/test/ui/traits/matching-lifetimes.stderr | 8 ++--- .../param-without-lifetime-constraint.stderr | 4 +-- .../self-without-lifetime-constraint.stderr | 4 +-- src/test/ui/unsafe/unsafe-trait-impl.rs | 4 +-- src/test/ui/unsafe/unsafe-trait-impl.stderr | 4 +-- src/test/ui/wrong-mul-method-signature.stderr | 12 +++---- 39 files changed, 169 insertions(+), 142 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 52babec4f9ea..c1cb07cf0dfe 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -253,8 +253,8 @@ infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not ge infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature .found = found `{$found}` .expected = expected `{$expected}` - .expected_found = expected `{$expected}` - {" "}found `{$found}` + .expected_found = expected signature `{$expected}` + {" "}found signature `{$found}` infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output infer_tid_consider_borrowing = consider borrowing this type parameter in the trait diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index a767338ab85c..0d3391bbc1ef 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -270,8 +270,8 @@ fn compare_method_predicate_entailment<'tcx>( let unnormalized_impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(unnormalized_impl_sig)); let norm_cause = ObligationCause::misc(impl_m_span, impl_m_hir_id); - let impl_fty = ocx.normalize(&norm_cause, param_env, unnormalized_impl_fty); - debug!("compare_impl_method: impl_fty={:?}", impl_fty); + let impl_sig = ocx.normalize(&norm_cause, param_env, unnormalized_impl_sig); + debug!("compare_impl_method: impl_fty={:?}", impl_sig); let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs); let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig); @@ -294,18 +294,17 @@ fn compare_method_predicate_entailment<'tcx>( // type would be more appropriate. In other places we have a `Vec` // corresponding to their `Vec`, but we don't have that here. // Fixing this would improve the output of test `issue-83765.rs`. - let result = ocx.sup(&cause, param_env, trait_fty, impl_fty); + let result = ocx.sup(&cause, param_env, trait_sig, impl_sig); if let Err(terr) = result { - debug!(?terr, "sub_types failed: impl ty {:?}, trait ty {:?}", impl_fty, trait_fty); + debug!(?impl_sig, ?trait_sig, ?terr, "sub_types failed"); let emitted = report_trait_method_mismatch( &infcx, cause, terr, - (trait_m, trait_fty), - (impl_m, impl_fty), - trait_sig, + (trait_m, trait_sig), + (impl_m, impl_sig), impl_trait_ref, ); return Err(emitted); @@ -484,7 +483,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( let impl_trait_ref = tcx.impl_trait_ref(impl_m.impl_container(tcx).unwrap()).unwrap(); let param_env = tcx.param_env(def_id); - // First, check a few of the same thing as `compare_impl_method`, just so we don't ICE during substitutions later. + // First, check a few of the same things as `compare_impl_method`, + // just so we don't ICE during substitution later. compare_number_of_generics(tcx, impl_m, trait_m, tcx.hir().span_if_local(impl_m.def_id), true)?; compare_generic_param_kinds(tcx, impl_m, trait_m, true)?; check_region_bounds_on_impl_item(tcx, impl_m, trait_m, true)?; @@ -577,14 +577,11 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( debug!(?trait_sig, ?impl_sig, "equating function signatures"); - let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); - let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); - // Unify the whole function signature. We need to do this to fully infer // the lifetimes of the return type, but do this after unifying just the // return types, since we want to avoid duplicating errors from // `compare_method_predicate_entailment`. - match ocx.eq(&cause, param_env, trait_fty, impl_fty) { + match ocx.eq(&cause, param_env, trait_sig, impl_sig) { Ok(()) => {} Err(terr) => { // This function gets called during `compare_method_predicate_entailment` when normalizing a @@ -595,9 +592,8 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( infcx, cause, terr, - (trait_m, trait_fty), - (impl_m, impl_fty), - trait_sig, + (trait_m, trait_sig), + (impl_m, impl_sig), impl_trait_ref, ); return Err(emitted); @@ -771,9 +767,8 @@ fn report_trait_method_mismatch<'tcx>( infcx: &InferCtxt<'tcx>, mut cause: ObligationCause<'tcx>, terr: TypeError<'tcx>, - (trait_m, trait_fty): (&ty::AssocItem, Ty<'tcx>), - (impl_m, impl_fty): (&ty::AssocItem, Ty<'tcx>), - trait_sig: ty::FnSig<'tcx>, + (trait_m, trait_sig): (&ty::AssocItem, ty::FnSig<'tcx>), + (impl_m, impl_sig): (&ty::AssocItem, ty::FnSig<'tcx>), impl_trait_ref: ty::TraitRef<'tcx>, ) -> ErrorGuaranteed { let tcx = infcx.tcx; @@ -858,10 +853,7 @@ fn report_trait_method_mismatch<'tcx>( &mut diag, &cause, trait_err_span.map(|sp| (sp, "type in trait".to_owned())), - Some(infer::ValuePairs::Terms(ExpectedFound { - expected: trait_fty.into(), - found: impl_fty.into(), - })), + Some(infer::ValuePairs::Sigs(ExpectedFound { expected: trait_sig, found: impl_sig })), terr, false, false, diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index e9186540a7b7..d816a9ed3d7c 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -427,3 +427,15 @@ impl<'tcx> ToTrace<'tcx> for ty::AliasTy<'tcx> { } } } + +impl<'tcx> ToTrace<'tcx> for ty::FnSig<'tcx> { + fn to_trace( + _: TyCtxt<'tcx>, + cause: &ObligationCause<'tcx>, + a_is_expected: bool, + a: Self, + b: Self, + ) -> TypeTrace<'tcx> { + TypeTrace { cause: cause.clone(), values: Sigs(ExpectedFound::new(a_is_expected, a, b)) } + } +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 0644c7ada10f..391804e35e2c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1429,8 +1429,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { impl<'tcx> OpaqueTypesVisitor<'tcx> { fn visit_expected_found( tcx: TyCtxt<'tcx>, - expected: Ty<'tcx>, - found: Ty<'tcx>, + expected: impl TypeVisitable<'tcx>, + found: impl TypeVisitable<'tcx>, ignore_span: Span, ) -> Self { let mut types_visitor = OpaqueTypesVisitor { @@ -1570,6 +1570,11 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _ => (false, Mismatch::Fixed("type")), } } + ValuePairs::Sigs(infer::ExpectedFound { expected, found }) => { + OpaqueTypesVisitor::visit_expected_found(self.tcx, expected, found, span) + .report(diag); + (false, Mismatch::Fixed("signature")) + } ValuePairs::TraitRefs(_) | ValuePairs::PolyTraitRefs(_) => { (false, Mismatch::Fixed("trait")) } @@ -2041,6 +2046,17 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ret => ret, } } + infer::Sigs(exp_found) => { + let exp_found = self.resolve_vars_if_possible(exp_found); + if exp_found.references_error() { + return None; + } + let (exp, fnd) = self.cmp_fn_sig( + &ty::Binder::dummy(exp_found.expected), + &ty::Binder::dummy(exp_found.found), + ); + Some((exp, fnd, None, None)) + } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 17c887a132aa..40c0c806e1ff 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -3,7 +3,7 @@ use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::infer::Subtype; +use crate::infer::{Subtype, ValuePairs}; use crate::traits::ObligationCauseCode::CompareImplItemObligation; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; @@ -11,6 +11,7 @@ use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_middle::hir::nested_filter; +use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::RegionHighlightMode; use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor}; use rustc_span::Span; @@ -23,22 +24,27 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let error = self.error.as_ref()?; debug!("try_report_impl_not_conforming_to_trait {:?}", error); if let RegionResolutionError::SubSupConflict( - _, - var_origin, - sub_origin, - _sub, - sup_origin, - _sup, - _, - ) = error.clone() + _, + var_origin, + sub_origin, + _sub, + sup_origin, + _sup, + _, + ) = error.clone() && let (Subtype(sup_trace), Subtype(sub_trace)) = (&sup_origin, &sub_origin) - && let sub_expected_found @ Some((sub_expected, sub_found)) = sub_trace.values.ty() - && let sup_expected_found @ Some(_) = sup_trace.values.ty() && let CompareImplItemObligation { trait_item_def_id, .. } = sub_trace.cause.code() - && sup_expected_found == sub_expected_found + && sub_trace.values == sup_trace.values + && let ValuePairs::Sigs(ExpectedFound { expected, found }) = sub_trace.values { - let guar = - self.emit_err(var_origin.span(), sub_expected, sub_found, *trait_item_def_id); + // FIXME(compiler-errors): Don't like that this needs `Ty`s, but + // all of the region highlighting machinery only deals with those. + let guar = self.emit_err( + var_origin.span(), + self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(expected)), + self.cx.tcx.mk_fn_ptr(ty::Binder::dummy(found)), + *trait_item_def_id, + ); return Some(guar); } None diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index b17a465eb383..f81ab60c5f66 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -361,6 +361,7 @@ pub enum ValuePairs<'tcx> { Terms(ExpectedFound>), TraitRefs(ExpectedFound>), PolyTraitRefs(ExpectedFound>), + Sigs(ExpectedFound>), } impl<'tcx> ValuePairs<'tcx> { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 8df326351fa0..7e21f7fc306d 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -22,8 +22,8 @@ note: type in trait | LL | fn make() -> Self::Ty { | ^^^^^^^^ - = note: expected fn pointer `fn() -> as Tr>::Ty` - found fn pointer `fn() -> u8` + = note: expected signature `fn() -> as Tr>::Ty` + found signature `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait --> $DIR/defaults-specialization.rs:35:18 @@ -42,8 +42,8 @@ note: type in trait | LL | fn make() -> Self::Ty { | ^^^^^^^^ - = note: expected fn pointer `fn() -> as Tr>::Ty` - found fn pointer `fn() -> bool` + = note: expected signature `fn() -> as Tr>::Ty` + found signature `fn() -> bool` error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:10:9 diff --git a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr index 22d2928f2f56..13e7222551aa 100644 --- a/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr +++ b/src/test/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | fn foo(&self) -> Pin + '_>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected fn pointer `fn(&i32) -> Pin>>` - found fn pointer `fn(&i32) -> impl Future` + = note: expected signature `fn(&i32) -> Pin>>` + found signature `fn(&i32) -> impl Future` error: aborting due to previous error diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 1e3b071ef929..930fea9158d4 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` - found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` + = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | @@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` - found fn pointer `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` + = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)` + found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)` note: the lifetime `'c` as defined here... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | diff --git a/src/test/ui/compare-method/bad-self-type.stderr b/src/test/ui/compare-method/bad-self-type.stderr index 90e907157a50..cad942e646e3 100644 --- a/src/test/ui/compare-method/bad-self-type.stderr +++ b/src/test/ui/compare-method/bad-self-type.stderr @@ -7,8 +7,8 @@ LL | fn poll(self, _: &mut Context<'_>) -> Poll<()> { | expected struct `Pin`, found struct `MyFuture` | help: change the self-receiver type to match the trait: `self: Pin<&mut MyFuture>` | - = note: expected fn pointer `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>` - found fn pointer `fn(MyFuture, &mut Context<'_>) -> Poll<_>` + = note: expected signature `fn(Pin<&mut MyFuture>, &mut Context<'_>) -> Poll<_>` + found signature `fn(MyFuture, &mut Context<'_>) -> Poll<_>` error[E0053]: method `foo` has an incompatible type for trait --> $DIR/bad-self-type.rs:22:18 @@ -24,8 +24,8 @@ note: type in trait | LL | fn foo(self); | ^^^^ - = note: expected fn pointer `fn(MyFuture)` - found fn pointer `fn(Box)` + = note: expected signature `fn(MyFuture)` + found signature `fn(Box)` error[E0053]: method `bar` has an incompatible type for trait --> $DIR/bad-self-type.rs:24:18 @@ -38,8 +38,8 @@ note: type in trait | LL | fn bar(self) -> Option<()>; | ^^^^^^^^^^ - = note: expected fn pointer `fn(MyFuture) -> Option<()>` - found fn pointer `fn(MyFuture)` + = note: expected signature `fn(MyFuture) -> Option<()>` + found signature `fn(MyFuture)` help: change the output type to match the trait | LL | fn bar(self) -> Option<()> {} diff --git a/src/test/ui/compare-method/issue-90444.stderr b/src/test/ui/compare-method/issue-90444.stderr index ee63f34b799a..52e23d03b148 100644 --- a/src/test/ui/compare-method/issue-90444.stderr +++ b/src/test/ui/compare-method/issue-90444.stderr @@ -7,8 +7,8 @@ LL | fn from(_: fn((), (), &mut ())) -> Self { | types differ in mutability | help: change the parameter type to match the trait: `for<'a> fn((), (), &'a ())` | - = note: expected fn pointer `fn(for<'a> fn((), (), &'a ())) -> A` - found fn pointer `fn(for<'a> fn((), (), &'a mut ())) -> A` + = note: expected signature `fn(for<'a> fn((), (), &'a ())) -> A` + found signature `fn(for<'a> fn((), (), &'a mut ())) -> A` error[E0053]: method `from` has an incompatible type for trait --> $DIR/issue-90444.rs:11:16 @@ -19,8 +19,8 @@ LL | fn from(_: fn((), (), u64)) -> Self { | expected `u32`, found `u64` | help: change the parameter type to match the trait: `fn((), (), u32)` | - = note: expected fn pointer `fn(fn((), (), u32)) -> B` - found fn pointer `fn(fn((), (), u64)) -> B` + = note: expected signature `fn(fn((), (), u32)) -> B` + found signature `fn(fn((), (), u64)) -> B` error: aborting due to 2 previous errors diff --git a/src/test/ui/compare-method/reordered-type-param.stderr b/src/test/ui/compare-method/reordered-type-param.stderr index 49b5b1b92cd0..1552d542d15d 100644 --- a/src/test/ui/compare-method/reordered-type-param.stderr +++ b/src/test/ui/compare-method/reordered-type-param.stderr @@ -14,8 +14,8 @@ note: type in trait | LL | fn b(&self, x: C) -> C; | ^ - = note: expected fn pointer `fn(&E, F) -> F` - found fn pointer `fn(&E, G) -> G` + = note: expected signature `fn(&E, F) -> F` + found signature `fn(&E, G) -> G` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr index acf768d5795e..db97fc2bdc46 100644 --- a/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr +++ b/src/test/ui/impl-trait/impl-generic-mismatch-ab.stderr @@ -13,8 +13,8 @@ note: type in trait | LL | fn foo(&self, a: &A, b: &impl Debug); | ^^ - = note: expected fn pointer `fn(&(), &B, &impl Debug)` - found fn pointer `fn(&(), &impl Debug, &B)` + = note: expected signature `fn(&(), &B, &impl Debug)` + found signature `fn(&(), &impl Debug, &B)` = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr index 2b32c52c829e..4dfd772222e5 100644 --- a/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr +++ b/src/test/ui/impl-trait/in-trait/method-signature-matches.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn owo(x: ()) -> impl Sized; | ^^ - = note: expected fn pointer `fn(())` - found fn pointer `fn(u8)` + = note: expected signature `fn(())` + found signature `fn(u8)` error[E0053]: method `owo` has an incompatible type for trait --> $DIR/method-signature-matches.rs:20:21 @@ -39,8 +39,8 @@ note: type in trait | LL | async fn owo(x: ()) {} | ^^ - = note: expected fn pointer `fn(()) -> _` - found fn pointer `fn(u8) -> _` + = note: expected signature `fn(()) -> _` + found signature `fn(u8) -> _` error[E0050]: method `calm_down_please` has 3 parameters but the declaration in trait `TooMuch::calm_down_please` has 0 --> $DIR/method-signature-matches.rs:29:28 @@ -75,8 +75,8 @@ note: type in trait | LL | fn early<'early, T>(x: &'early T) -> impl Sized; | ^^^^^^^^^ - = note: expected fn pointer `fn(&'early T)` - found fn pointer `fn(&())` + = note: expected signature `fn(&'early T)` + found signature `fn(&())` error: aborting due to 5 previous errors diff --git a/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr index 6663d7faa1e5..e105660173b4 100644 --- a/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr +++ b/src/test/ui/impl-trait/in-trait/signature-mismatch.stderr @@ -7,8 +7,8 @@ LL | fn async_fn(&self, buff: &[u8]) -> impl Future>; LL | fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future> + 'a { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Struct, &'2 [u8]) -> impl Future> + '2` | - = note: expected `fn(&'1 Struct, &'2 [u8]) -> impl Future> + 'static` - found `fn(&'1 Struct, &'2 [u8]) -> impl Future> + '2` + = note: expected signature `fn(&'1 Struct, &'2 [u8]) -> impl Future> + 'static` + found signature `fn(&'1 Struct, &'2 [u8]) -> impl Future> + '2` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr index a30e6346b292..37cfd74498d8 100644 --- a/src/test/ui/impl-trait/in-trait/specialization-broken.stderr +++ b/src/test/ui/impl-trait/in-trait/specialization-broken.stderr @@ -15,8 +15,8 @@ note: type in trait | LL | fn bar(&self) -> impl Sized; | ^^^^^^^^^^ - = note: expected fn pointer `fn(&U) -> impl Sized` - found fn pointer `fn(&U) -> U` + = note: expected signature `fn(&U) -> impl Sized` + found signature `fn(&U) -> U` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index 3ee26f74a787..c7c6ca440126 100644 --- a/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/src/test/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -18,8 +18,8 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { | expected struct `Bar`, found opaque type | help: change the parameter type to match the trait: `&(a::Bar, i32)` | - = note: expected fn pointer `fn(&a::Bar, &(a::Bar, i32)) -> _` - found fn pointer `fn(&a::Bar, &(a::Foo, i32)) -> _` + = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _` + found signature `fn(&a::Bar, &(a::Foo, i32)) -> _` error: unconstrained opaque type --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16 @@ -41,8 +41,8 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool { | expected opaque type, found struct `Bar` | help: change the parameter type to match the trait: `&(b::Foo, i32)` | - = note: expected fn pointer `fn(&b::Bar, &(b::Foo, i32)) -> _` - found fn pointer `fn(&b::Bar, &(b::Bar, i32)) -> _` + = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _` + found signature `fn(&b::Bar, &(b::Bar, i32)) -> _` error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/trait_type.stderr b/src/test/ui/impl-trait/trait_type.stderr index bea24339837a..81e4c933e53f 100644 --- a/src/test/ui/impl-trait/trait_type.stderr +++ b/src/test/ui/impl-trait/trait_type.stderr @@ -7,8 +7,8 @@ LL | fn fmt(&self, x: &str) -> () { } | types differ in mutability | help: change the parameter type to match the trait: `&mut Formatter<'_>` | - = note: expected fn pointer `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` - found fn pointer `fn(&MyType, &str)` + = note: expected signature `fn(&MyType, &mut Formatter<'_>) -> Result<(), std::fmt::Error>` + found signature `fn(&MyType, &str)` error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2 --> $DIR/trait_type.rs:12:11 diff --git a/src/test/ui/issues/issue-13033.rs b/src/test/ui/issues/issue-13033.rs index 7631831a81a5..fdb356e70c5f 100644 --- a/src/test/ui/issues/issue-13033.rs +++ b/src/test/ui/issues/issue-13033.rs @@ -7,8 +7,8 @@ struct Baz; impl Foo for Baz { fn bar(&mut self, other: &dyn Foo) {} //~^ ERROR method `bar` has an incompatible type for trait - //~| expected fn pointer `fn(&mut Baz, &mut dyn Foo)` - //~| found fn pointer `fn(&mut Baz, &dyn Foo)` + //~| expected signature `fn(&mut Baz, &mut dyn Foo)` + //~| found signature `fn(&mut Baz, &dyn Foo)` } fn main() {} diff --git a/src/test/ui/issues/issue-13033.stderr b/src/test/ui/issues/issue-13033.stderr index 72e549813e81..db2c1189e1e1 100644 --- a/src/test/ui/issues/issue-13033.stderr +++ b/src/test/ui/issues/issue-13033.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn bar(&mut self, other: &mut dyn Foo); | ^^^^^^^^^^^^ - = note: expected fn pointer `fn(&mut Baz, &mut dyn Foo)` - found fn pointer `fn(&mut Baz, &dyn Foo)` + = note: expected signature `fn(&mut Baz, &mut dyn Foo)` + found signature `fn(&mut Baz, &dyn Foo)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-15094.rs b/src/test/ui/issues/issue-15094.rs index 71b75a6e7e00..cb27e2bcfb6c 100644 --- a/src/test/ui/issues/issue-15094.rs +++ b/src/test/ui/issues/issue-15094.rs @@ -10,8 +10,8 @@ impl ops::FnOnce<(),> for Debuger { type Output = (); fn call_once(self, _args: ()) { //~^ ERROR `call_once` has an incompatible type for trait - //~| expected fn pointer `extern "rust-call" fn - //~| found fn pointer `fn + //~| expected signature `extern "rust-call" fn + //~| found signature `fn println!("{:?}", self.x); } } diff --git a/src/test/ui/issues/issue-15094.stderr b/src/test/ui/issues/issue-15094.stderr index 2dcdaba170ac..b7c950892dc2 100644 --- a/src/test/ui/issues/issue-15094.stderr +++ b/src/test/ui/issues/issue-15094.stderr @@ -4,8 +4,8 @@ error[E0053]: method `call_once` has an incompatible type for trait LL | fn call_once(self, _args: ()) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected "rust-call" fn, found "Rust" fn | - = note: expected fn pointer `extern "rust-call" fn(Debuger<_>, ())` - found fn pointer `fn(Debuger<_>, ())` + = note: expected signature `extern "rust-call" fn(Debuger<_>, ())` + found signature `fn(Debuger<_>, ())` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20225.stderr b/src/test/ui/issues/issue-20225.stderr index 6f4813ca6235..5822160107cc 100644 --- a/src/test/ui/issues/issue-20225.stderr +++ b/src/test/ui/issues/issue-20225.stderr @@ -9,8 +9,8 @@ LL | extern "rust-call" fn call(&self, (_,): (T,)) {} | expected `&T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected fn pointer `extern "rust-call" fn(&Foo, (&'a T,))` - found fn pointer `extern "rust-call" fn(&Foo, (T,))` + = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))` + found signature `extern "rust-call" fn(&Foo, (T,))` error[E0053]: method `call_mut` has an incompatible type for trait --> $DIR/issue-20225.rs:11:51 @@ -23,8 +23,8 @@ LL | extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {} | expected `&T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected fn pointer `extern "rust-call" fn(&mut Foo, (&'a T,))` - found fn pointer `extern "rust-call" fn(&mut Foo, (T,))` + = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))` + found signature `extern "rust-call" fn(&mut Foo, (T,))` error[E0053]: method `call_once` has an incompatible type for trait --> $DIR/issue-20225.rs:18:47 @@ -38,8 +38,8 @@ LL | extern "rust-call" fn call_once(self, (_,): (T,)) {} | expected `&T`, found type parameter `T` | help: change the parameter type to match the trait: `(&'a T,)` | - = note: expected fn pointer `extern "rust-call" fn(Foo, (&'a T,))` - found fn pointer `extern "rust-call" fn(Foo, (T,))` + = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))` + found signature `extern "rust-call" fn(Foo, (T,))` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-21332.stderr b/src/test/ui/issues/issue-21332.stderr index d92966da17c4..0e1beebf2931 100644 --- a/src/test/ui/issues/issue-21332.stderr +++ b/src/test/ui/issues/issue-21332.stderr @@ -7,8 +7,8 @@ LL | fn next(&mut self) -> Result { Ok(7) } | expected enum `Option`, found enum `Result` | help: change the output type to match the trait: `Option` | - = note: expected fn pointer `fn(&mut S) -> Option` - found fn pointer `fn(&mut S) -> Result` + = note: expected signature `fn(&mut S) -> Option` + found signature `fn(&mut S) -> Result` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index e9f50b41f6ac..7ddb36c8e6f7 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait LL | fn next(&'a mut self) -> Option | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>` - found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` + = note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>` + found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>` note: the anonymous lifetime as defined here... --> $DIR/issue-37884.rs:6:5 | diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 3040a8512ce1..9c61d5a0c25e 100644 --- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -7,8 +7,8 @@ LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32` | - = note: expected `fn(&'1 i32, &'a i32) -> &'a i32` - found `fn(&'1 i32, &'1 i32) -> &'1 i32` + = note: expected signature `fn(&'1 i32, &'a i32) -> &'a i32` + found signature `fn(&'1 i32, &'1 i32) -> &'1 i32` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/mismatched_types/E0053.stderr b/src/test/ui/mismatched_types/E0053.stderr index 54b419264514..154f2fcbee0f 100644 --- a/src/test/ui/mismatched_types/E0053.stderr +++ b/src/test/ui/mismatched_types/E0053.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn foo(x: u16); | ^^^ - = note: expected fn pointer `fn(u16)` - found fn pointer `fn(i16)` + = note: expected signature `fn(u16)` + found signature `fn(i16)` error[E0053]: method `bar` has an incompatible type for trait --> $DIR/E0053.rs:11:12 @@ -29,8 +29,8 @@ note: type in trait | LL | fn bar(&self); | ^^^^^ - = note: expected fn pointer `fn(&Bar)` - found fn pointer `fn(&mut Bar)` + = note: expected signature `fn(&Bar)` + found signature `fn(&mut Bar)` error: aborting due to 2 previous errors diff --git a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr index b75c7a99fdd3..9ddea1629445 100644 --- a/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr +++ b/src/test/ui/mismatched_types/issue-74918-missing-lifetime.stderr @@ -18,8 +18,8 @@ LL | fn next(&mut self) -> Option> { | = note: expected `fn(&'1 mut ChunkingIterator) -> Option>` | - = note: expected `fn(&'1 mut ChunkingIterator) -> Option>` - found `fn(&'1 mut ChunkingIterator) -> Option>` + = note: expected signature `fn(&'1 mut ChunkingIterator) -> Option>` + found signature `fn(&'1 mut ChunkingIterator) -> Option>` = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output diff --git a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr index 2a2c23c94212..88416ba4bb6d 100644 --- a/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/src/test/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -7,8 +7,8 @@ LL | fn adjacent_edges(&self) -> Box>; LL | fn adjacent_edges(&self) -> Box + '_> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` | - = note: expected `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` - found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` + = note: expected signature `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` + found signature `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/issue-75361-mismatched-impl.rs:12:55 | diff --git a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 6b2ba53daa08..6e7bf5eb46d9 100644 --- a/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/src/test/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn foo(x: u16); | ^^^ - = note: expected fn pointer `fn(u16)` - found fn pointer `fn(i16)` + = note: expected signature `fn(u16)` + found signature `fn(i16)` error[E0053]: method `bar` has an incompatible type for trait --> $DIR/trait-impl-fn-incompatibility.rs:10:28 @@ -29,8 +29,8 @@ note: type in trait | LL | fn bar(&mut self, bar: &mut Bar); | ^^^^^^^^ - = note: expected fn pointer `fn(&mut Bar, &mut Bar)` - found fn pointer `fn(&mut Bar, &Bar)` + = note: expected signature `fn(&mut Bar, &mut Bar)` + found signature `fn(&mut Bar, &Bar)` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/impl-method-mismatch.rs b/src/test/ui/traits/impl-method-mismatch.rs index 683b1c1aa43e..62580755c814 100644 --- a/src/test/ui/traits/impl-method-mismatch.rs +++ b/src/test/ui/traits/impl-method-mismatch.rs @@ -6,8 +6,8 @@ impl Mumbo for usize { // Cannot have a larger effect than the trait: unsafe fn jumbo(&self, x: &usize) { *self + *x; } //~^ ERROR method `jumbo` has an incompatible type for trait - //~| expected fn pointer `fn - //~| found fn pointer `unsafe fn + //~| expected signature `fn + //~| found signature `unsafe fn } fn main() {} diff --git a/src/test/ui/traits/impl-method-mismatch.stderr b/src/test/ui/traits/impl-method-mismatch.stderr index 30aa97d2934d..252b5aff96a0 100644 --- a/src/test/ui/traits/impl-method-mismatch.stderr +++ b/src/test/ui/traits/impl-method-mismatch.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | fn jumbo(&self, x: &usize) -> usize; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected fn pointer `fn(&usize, &usize) -> usize` - found fn pointer `unsafe fn(&usize, &usize)` + = note: expected signature `fn(&usize, &usize) -> usize` + found signature `unsafe fn(&usize, &usize)` error: aborting due to previous error diff --git a/src/test/ui/traits/issue-35869.stderr b/src/test/ui/traits/issue-35869.stderr index 0780109b8432..6d985bdeaf85 100644 --- a/src/test/ui/traits/issue-35869.stderr +++ b/src/test/ui/traits/issue-35869.stderr @@ -12,8 +12,8 @@ note: type in trait | LL | fn foo(_: fn(u8) -> ()); | ^^^^^^^^^^^^ - = note: expected fn pointer `fn(fn(u8))` - found fn pointer `fn(fn(u16))` + = note: expected signature `fn(fn(u8))` + found signature `fn(fn(u16))` error[E0053]: method `bar` has an incompatible type for trait --> $DIR/issue-35869.rs:13:15 @@ -29,8 +29,8 @@ note: type in trait | LL | fn bar(_: Option); | ^^^^^^^^^^ - = note: expected fn pointer `fn(Option)` - found fn pointer `fn(Option)` + = note: expected signature `fn(Option)` + found signature `fn(Option)` error[E0053]: method `baz` has an incompatible type for trait --> $DIR/issue-35869.rs:15:15 @@ -46,8 +46,8 @@ note: type in trait | LL | fn baz(_: (u8, u16)); | ^^^^^^^^^ - = note: expected fn pointer `fn((u8, _))` - found fn pointer `fn((u16, _))` + = note: expected signature `fn((u8, _))` + found signature `fn((u16, _))` error[E0053]: method `qux` has an incompatible type for trait --> $DIR/issue-35869.rs:17:17 @@ -63,8 +63,8 @@ note: type in trait | LL | fn qux() -> u8; | ^^ - = note: expected fn pointer `fn() -> u8` - found fn pointer `fn() -> u16` + = note: expected signature `fn() -> u8` + found signature `fn() -> u16` error: aborting due to 4 previous errors diff --git a/src/test/ui/traits/matching-lifetimes.stderr b/src/test/ui/traits/matching-lifetimes.stderr index de1c878a5131..f8119ed415d0 100644 --- a/src/test/ui/traits/matching-lifetimes.stderr +++ b/src/test/ui/traits/matching-lifetimes.stderr @@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait LL | fn foo(x: Foo<'b,'a>) { | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(Foo<'a, 'b>)` - found fn pointer `fn(Foo<'b, 'a>)` + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` note: the lifetime `'b` as defined here... --> $DIR/matching-lifetimes.rs:13:9 | @@ -23,8 +23,8 @@ error[E0308]: method not compatible with trait LL | fn foo(x: Foo<'b,'a>) { | ^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected fn pointer `fn(Foo<'a, 'b>)` - found fn pointer `fn(Foo<'b, 'a>)` + = note: expected signature `fn(Foo<'a, 'b>)` + found signature `fn(Foo<'b, 'a>)` note: the lifetime `'a` as defined here... --> $DIR/matching-lifetimes.rs:13:6 | diff --git a/src/test/ui/traits/param-without-lifetime-constraint.stderr b/src/test/ui/traits/param-without-lifetime-constraint.stderr index 118b2cf3ecd8..b128b6518ce4 100644 --- a/src/test/ui/traits/param-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/param-without-lifetime-constraint.stderr @@ -7,8 +7,8 @@ LL | fn get_relation(&self) -> To; LL | fn get_relation(&self) -> &ProofReader { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` | - = note: expected `fn(&'1 Article) -> &'2 ProofReader` - found `fn(&'1 Article) -> &'1 ProofReader` + = note: expected signature `fn(&'1 Article) -> &'2 ProofReader` + found signature `fn(&'1 Article) -> &'1 ProofReader` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/param-without-lifetime-constraint.rs:10:31 | diff --git a/src/test/ui/traits/self-without-lifetime-constraint.stderr b/src/test/ui/traits/self-without-lifetime-constraint.stderr index 85fada3b87c3..05a49820a822 100644 --- a/src/test/ui/traits/self-without-lifetime-constraint.stderr +++ b/src/test/ui/traits/self-without-lifetime-constraint.stderr @@ -7,8 +7,8 @@ LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` | - = note: expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` - found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` + = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` + found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/self-without-lifetime-constraint.rs:41:60 | diff --git a/src/test/ui/unsafe/unsafe-trait-impl.rs b/src/test/ui/unsafe/unsafe-trait-impl.rs index 03a251be1a91..1fc84ca02560 100644 --- a/src/test/ui/unsafe/unsafe-trait-impl.rs +++ b/src/test/ui/unsafe/unsafe-trait-impl.rs @@ -7,8 +7,8 @@ trait Foo { impl Foo for u32 { fn len(&self) -> u32 { *self } //~^ ERROR method `len` has an incompatible type for trait - //~| expected fn pointer `unsafe fn(&u32) -> _` - //~| found fn pointer `fn(&u32) -> _` + //~| expected signature `unsafe fn(&u32) -> _` + //~| found signature `fn(&u32) -> _` } fn main() { } diff --git a/src/test/ui/unsafe/unsafe-trait-impl.stderr b/src/test/ui/unsafe/unsafe-trait-impl.stderr index 8a0cba1fac55..18ba79404b77 100644 --- a/src/test/ui/unsafe/unsafe-trait-impl.stderr +++ b/src/test/ui/unsafe/unsafe-trait-impl.stderr @@ -9,8 +9,8 @@ note: type in trait | LL | unsafe fn len(&self) -> u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: expected fn pointer `unsafe fn(&u32) -> _` - found fn pointer `fn(&u32) -> _` + = note: expected signature `unsafe fn(&u32) -> _` + found signature `fn(&u32) -> _` error: aborting due to previous error diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr index 8338f61b22a7..504a6032b01f 100644 --- a/src/test/ui/wrong-mul-method-signature.stderr +++ b/src/test/ui/wrong-mul-method-signature.stderr @@ -7,8 +7,8 @@ LL | fn mul(self, s: &f64) -> Vec1 { | expected `f64`, found `&f64` | help: change the parameter type to match the trait: `f64` | - = note: expected fn pointer `fn(Vec1, f64) -> Vec1` - found fn pointer `fn(Vec1, &f64) -> Vec1` + = note: expected signature `fn(Vec1, f64) -> Vec1` + found signature `fn(Vec1, &f64) -> Vec1` error[E0053]: method `mul` has an incompatible type for trait --> $DIR/wrong-mul-method-signature.rs:33:21 @@ -19,8 +19,8 @@ LL | fn mul(self, s: f64) -> Vec2 { | expected struct `Vec2`, found `f64` | help: change the parameter type to match the trait: `Vec2` | - = note: expected fn pointer `fn(Vec2, Vec2) -> f64` - found fn pointer `fn(Vec2, f64) -> Vec2` + = note: expected signature `fn(Vec2, Vec2) -> f64` + found signature `fn(Vec2, f64) -> Vec2` error[E0053]: method `mul` has an incompatible type for trait --> $DIR/wrong-mul-method-signature.rs:52:29 @@ -31,8 +31,8 @@ LL | fn mul(self, s: f64) -> f64 { | expected `i32`, found `f64` | help: change the output type to match the trait: `i32` | - = note: expected fn pointer `fn(Vec3, _) -> i32` - found fn pointer `fn(Vec3, _) -> f64` + = note: expected signature `fn(Vec3, _) -> i32` + found signature `fn(Vec3, _) -> f64` error[E0308]: mismatched types --> $DIR/wrong-mul-method-signature.rs:63:45 From 0e570e58f2cf465f254b7e6c56584ec732a77dbc Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 8 Jan 2023 22:51:42 +0800 Subject: [PATCH 215/223] Remove extra space --- .../ui/suggestions/issue-106443-sugg-clone-for-bound.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr index 22bafc6cc8b9..8607917ede6b 100644 --- a/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr +++ b/src/test/ui/suggestions/issue-106443-sugg-clone-for-bound.stderr @@ -6,7 +6,7 @@ LL | foo(s); | help: consider further restricting this bound | -LL | fn bar(s: &T) { +LL | fn bar(s: &T) { | +++++++ help: consider using clone here | From ca554efaf78962f9dc9599663b29626269c69c8c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 02:40:59 +0000 Subject: [PATCH 216/223] Improve spans of non-WF implied bound types --- .../rustc_hir_analysis/src/check/wfcheck.rs | 58 ++++++---------- compiler/rustc_middle/src/query/mod.rs | 2 +- .../src/traits/engine.rs | 6 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 67 ++++++++++++++++--- .../associated-types-for-unimpl-trait.stderr | 4 +- .../associated-types-no-suitable-bound.stderr | 4 +- ...ated-types-no-suitable-supertrait-2.stderr | 4 +- ...ciated-types-no-suitable-supertrait.stderr | 8 +-- ...ted-trait-in-method-without-default.stderr | 4 +- src/test/ui/associated-types/issue-59324.rs | 2 +- .../ui/associated-types/issue-59324.stderr | 17 ++--- src/test/ui/issues/issue-18611.stderr | 8 +-- .../ui/issues/issue-20831-debruijn.stderr | 24 ++----- src/test/ui/issues/issue-35570.rs | 1 - src/test/ui/issues/issue-35570.stderr | 16 +---- .../ui/nll/normalization-bounds-error.stderr | 8 +-- ...ions-implied-bounds-projection-gap-hr-1.rs | 1 - ...-implied-bounds-projection-gap-hr-1.stderr | 21 +----- .../min_specialization/issue-79224.rs | 6 +- .../min_specialization/issue-79224.stderr | 18 ++--- src/test/ui/wf/issue-103573.stderr | 4 +- src/test/ui/wf/wf-foreign-fn-decl-ret.stderr | 4 +- 22 files changed, 134 insertions(+), 153 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 1afe62424037..b663f90cab71 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1489,54 +1489,38 @@ fn check_fn_or_method<'tcx>( def_id: LocalDefId, ) { let tcx = wfcx.tcx(); - let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); + let mut sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig); // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` // for each type, preventing the HIR wf check from generating // a nice error message. - let ty::FnSig { mut inputs_and_output, c_variadic, unsafety, abi } = sig; - inputs_and_output = tcx.mk_type_list(inputs_and_output.iter().enumerate().map(|(i, ty)| { - wfcx.normalize( - span, - Some(WellFormedLoc::Param { - function: def_id, - // Note that the `param_idx` of the output type is - // one greater than the index of the last input type. - param_idx: i.try_into().unwrap(), - }), - ty, - ) - })); - // Manually call `normalize_associated_types_in` on the other types - // in `FnSig`. This ensures that if the types of these fields - // ever change to include projections, we will start normalizing - // them automatically. - let sig = ty::FnSig { - inputs_and_output, - c_variadic: wfcx.normalize(span, None, c_variadic), - unsafety: wfcx.normalize(span, None, unsafety), - abi: wfcx.normalize(span, None, abi), - }; + let arg_span = + |idx| hir_decl.inputs.get(idx).map_or(hir_decl.output.span(), |arg: &hir::Ty<'_>| arg.span); - for (i, (&input_ty, ty)) in iter::zip(sig.inputs(), hir_decl.inputs).enumerate() { + sig.inputs_and_output = + tcx.mk_type_list(sig.inputs_and_output.iter().enumerate().map(|(idx, ty)| { + wfcx.normalize( + arg_span(idx), + Some(WellFormedLoc::Param { + function: def_id, + // Note that the `param_idx` of the output type is + // one greater than the index of the last input type. + param_idx: idx.try_into().unwrap(), + }), + ty, + ) + })); + + for (idx, ty) in sig.inputs_and_output.iter().enumerate() { wfcx.register_wf_obligation( - ty.span, - Some(WellFormedLoc::Param { function: def_id, param_idx: i.try_into().unwrap() }), - input_ty.into(), + arg_span(idx), + Some(WellFormedLoc::Param { function: def_id, param_idx: idx.try_into().unwrap() }), + ty.into(), ); } - wfcx.register_wf_obligation( - hir_decl.output.span(), - Some(WellFormedLoc::Param { - function: def_id, - param_idx: sig.inputs().len().try_into().unwrap(), - }), - sig.output().into(), - ); - check_where_clauses(wfcx, span, def_id); check_return_position_impl_trait_in_trait_bounds( diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 37db2274f678..7f794a926c06 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -803,7 +803,7 @@ rustc_queries! { /// /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: DefId) -> &'tcx ty::List> { + query assumed_wf_types(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index bc6d9d4b922d..72ed3aa499da 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -191,8 +191,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { let assumed_wf_types = tcx.assumed_wf_types(def_id); let mut implied_bounds = FxIndexSet::default(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let cause = ObligationCause::misc(span, hir_id); - for ty in assumed_wf_types { + for &(ty, ty_span) in assumed_wf_types { + let span = if ty_span.is_dummy() { span } else { ty_span }; // FIXME(@lcnr): rustc currently does not check wf for types // pre-normalization, meaning that implied bounds are sometimes // incorrect. See #100910 for more details. @@ -205,7 +205,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { // sound and then uncomment this line again. // implied_bounds.insert(ty); - let normalized = self.normalize(&cause, param_env, ty); + let normalized = self.normalize(&ObligationCause::misc(span, hir_id), param_env, ty); implied_bounds.insert(normalized); } implied_bounds diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index b7a24a22c53e..e3f34373ccc9 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -1,33 +1,80 @@ use crate::rustc_middle::ty::DefIdTree; -use rustc_hir::{def::DefKind, def_id::DefId}; +use rustc_hir::{self as hir, def::DefKind, def_id::DefId}; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_span::{Span, DUMMY_SP}; pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { assumed_wf_types, ..*providers }; } -fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { +fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &[(Ty<'_>, Span)] { match tcx.def_kind(def_id) { DefKind::Fn => { let sig = tcx.fn_sig(def_id); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); - liberated_sig.inputs_and_output + if let Some(node) = tcx.hir().get_if_local(def_id) + && let Some(decl) = node.fn_decl() + { + assert_eq!(decl.inputs.len(), liberated_sig.inputs().len()); + tcx.arena.alloc_from_iter(std::iter::zip( + liberated_sig.inputs_and_output, + decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]), + )) + } else { + tcx.arena.alloc_from_iter( + liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)), + ) + } } DefKind::AssocFn => { let sig = tcx.fn_sig(def_id); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); - let mut assumed_wf_types: Vec<_> = - tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); - assumed_wf_types.extend(liberated_sig.inputs_and_output); - tcx.intern_type_list(&assumed_wf_types) + let assumed_wf_types = tcx.assumed_wf_types(tcx.parent(def_id)); + if let Some(node) = tcx.hir().get_if_local(def_id) + && let Some(decl) = node.fn_decl() + { + assert_eq!(decl.inputs.len(), liberated_sig.inputs().len()); + tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain(std::iter::zip( + liberated_sig.inputs_and_output, + decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]), + ))) + } else { + tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain( + liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)), + )) + } } DefKind::Impl => match tcx.impl_trait_ref(def_id) { Some(trait_ref) => { let types: Vec<_> = trait_ref.substs.types().collect(); - tcx.intern_type_list(&types) + let self_span = if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(impl_), + .. + })) = tcx.hir().get_if_local(def_id) + { + impl_.self_ty.span + } else { + DUMMY_SP + }; + tcx.arena.alloc_from_iter(std::iter::zip( + types, + // FIXME: reliable way of getting trait ref substs... + [self_span].into_iter().chain(std::iter::repeat(DUMMY_SP)), + )) } // Only the impl self type - None => tcx.intern_type_list(&[tcx.type_of(def_id)]), + None => { + let span = if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(impl_), + .. + })) = tcx.hir().get_if_local(def_id) + { + impl_.self_ty.span + } else { + DUMMY_SP + }; + tcx.arena.alloc_from_iter([(tcx.type_of(def_id), span)]) + } }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), DefKind::Mod @@ -56,6 +103,6 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Closure - | DefKind::Generator => ty::List::empty(), + | DefKind::Generator => &[], } } diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 389cc7beddd8..6552c8be7808 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:10:5 + --> $DIR/associated-types-for-unimpl-trait.rs:10:40 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index 1feaa612ee68..b2ee1b5e6d04 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `T: Get` is not satisfied - --> $DIR/associated-types-no-suitable-bound.rs:11:5 + --> $DIR/associated-types-no-suitable-bound.rs:11:21 | LL | fn uhoh(foo: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index cc3ed556115b..2e40dbd065d3 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 + --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index 18f2830d8b21..bd3ee2abd2c7 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -1,14 +1,14 @@ error[E0277]: the trait bound `(T, U): Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 + --> $DIR/associated-types-no-suitable-supertrait.rs:22:40 | LL | fn uhoh(&self, foo: U, bar: <(T, U) as Get>::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)` error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 + --> $DIR/associated-types-no-suitable-supertrait.rs:17:40 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 66d59bccdbb6..2e67c21940fc 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40 | LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` | help: consider further restricting `Self` | diff --git a/src/test/ui/associated-types/issue-59324.rs b/src/test/ui/associated-types/issue-59324.rs index 9e68e9e77515..551f13ee178d 100644 --- a/src/test/ui/associated-types/issue-59324.rs +++ b/src/test/ui/associated-types/issue-59324.rs @@ -15,9 +15,9 @@ pub trait ThriftService: { fn get_service( //~^ ERROR the trait bound `Bug: Foo` is not satisfied - //~| ERROR the trait bound `Bug: Foo` is not satisfied &self, ) -> Self::AssocType; + //~^ ERROR the trait bound `Bug: Foo` is not satisfied } fn with_factory(factory: dyn ThriftService<()>) {} diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr index 62cf1f37a771..a84b599b52b6 100644 --- a/src/test/ui/associated-types/issue-59324.stderr +++ b/src/test/ui/associated-types/issue-59324.stderr @@ -20,7 +20,7 @@ LL | | LL | | LL | | Service::OnlyFoo> ... | -LL | | ) -> Self::AssocType; +LL | | LL | | } | |_^ the trait `Foo` is not implemented for `Bug` | @@ -34,7 +34,6 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied | LL | / fn get_service( LL | | -LL | | LL | | &self, LL | | ) -> Self::AssocType; | |_________________________^ the trait `Foo` is not implemented for `Bug` @@ -45,20 +44,16 @@ LL | pub trait ThriftService: | +++++ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/issue-59324.rs:23:1 + --> $DIR/issue-59324.rs:23:29 | LL | fn with_factory(factory: dyn ThriftService<()>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `Bug: Foo` is not satisfied - --> $DIR/issue-59324.rs:16:5 + --> $DIR/issue-59324.rs:19:10 | -LL | / fn get_service( -LL | | -LL | | -LL | | &self, -LL | | ) -> Self::AssocType; - | |_________________________^ the trait `Foo` is not implemented for `Bug` +LL | ) -> Self::AssocType; + | ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug` | help: consider further restricting this bound | diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr index 22c3470b61ed..bd18d46223e6 100644 --- a/src/test/ui/issues/issue-18611.stderr +++ b/src/test/ui/issues/issue-18611.stderr @@ -1,10 +1,8 @@ error[E0277]: the trait bound `isize: HasState` is not satisfied - --> $DIR/issue-18611.rs:1:1 + --> $DIR/issue-18611.rs:1:18 | -LL | / fn add_state(op: ::State) { -LL | | -LL | | } - | |_^ the trait `HasState` is not implemented for `isize` +LL | fn add_state(op: ::State) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index ef62dece8364..c3af1f6786b3 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -1,14 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements - --> $DIR/issue-20831-debruijn.rs:28:5 + --> $DIR/issue-20831-debruijn.rs:28:33 | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | // -... | -LL | | self.sub = t; -LL | | } - | |_____^ +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the anonymous lifetime defined here... --> $DIR/issue-20831-debruijn.rs:28:58 @@ -21,16 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he LL | impl<'a> Publisher<'a> for MyStruct<'a> { | ^^ note: ...so that the types are compatible - --> $DIR/issue-20831-debruijn.rs:28:5 + --> $DIR/issue-20831-debruijn.rs:28:33 | -LL | / fn subscribe(&mut self, t : Box::Output> + 'a>) { -LL | | // Not obvious, but there is an implicit lifetime here -------^ -LL | | -LL | | // -... | -LL | | self.sub = t; -LL | | } - | |_____^ +LL | fn subscribe(&mut self, t : Box::Output> + 'a>) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected ` as Publisher<'_>>` found ` as Publisher<'_>>` diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs index a2b0222d4f39..42bdb423f8f5 100644 --- a/src/test/ui/issues/issue-35570.rs +++ b/src/test/ui/issues/issue-35570.rs @@ -7,7 +7,6 @@ trait Trait2<'a> { fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied - //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied let _e: (usize, usize) = unsafe{mem::transmute(param)}; } diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr index ebc40f6786fd..b6c244241edd 100644 --- a/src/test/ui/issues/issue-35570.stderr +++ b/src/test/ui/issues/issue-35570.stderr @@ -1,19 +1,9 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:1 - | -LL | / fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { -LL | | -LL | | -LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)}; -LL | | } - | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()` - -error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:40 + --> $DIR/issue-35570.rs:8:16 | LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { - | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 6abe53127c3f..0fc3670d6c52 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -1,8 +1,8 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements - --> $DIR/normalization-bounds-error.rs:12:1 + --> $DIR/normalization-bounds-error.rs:12:31 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first, the lifetime cannot outlive the lifetime `'d` as defined here... --> $DIR/normalization-bounds-error.rs:12:14 @@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ note: ...so that the types are compatible - --> $DIR/normalization-bounds-error.rs:12:1 + --> $DIR/normalization-bounds-error.rs:12:31 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: expected `Visitor<'d>` found `Visitor<'_>` diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs index 1106352037a0..429548f119b1 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -20,7 +20,6 @@ trait Trait2<'a, 'b> { // do not infer that. fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied { } diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 66f592c34dd0..43b7b9c16b1c 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -1,29 +1,14 @@ error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1 - | -LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) -LL | | -LL | | -LL | | { -LL | | } - | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` - | -help: consider restricting type parameter `T` - | -LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ++++++++++++++++++++++++ - -error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49 + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:25 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | help: consider restricting type parameter `T` | LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/specialization/min_specialization/issue-79224.rs b/src/test/ui/specialization/min_specialization/issue-79224.rs index 408732fe944f..d02c108ae6bc 100644 --- a/src/test/ui/specialization/min_specialization/issue-79224.rs +++ b/src/test/ui/specialization/min_specialization/issue-79224.rs @@ -15,8 +15,10 @@ impl ToString for Cow<'_, str> { } } -impl Display for Cow<'_, B> { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277] - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { //~ ERROR: the trait bound `B: Clone` is not satisfied [E0277] +impl Display for Cow<'_, B> { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] + //~| ERROR: the trait bound `B: Clone` is not satisfied [E0277] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "foo") } } diff --git a/src/test/ui/specialization/min_specialization/issue-79224.stderr b/src/test/ui/specialization/min_specialization/issue-79224.stderr index fd34a59d2bd6..d4d7daf41117 100644 --- a/src/test/ui/specialization/min_specialization/issue-79224.stderr +++ b/src/test/ui/specialization/min_specialization/issue-79224.stderr @@ -1,12 +1,8 @@ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:18:1 + --> $DIR/issue-79224.rs:18:29 | -LL | / impl Display for Cow<'_, B> { -LL | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -LL | | write!(f, "foo") -LL | | } -LL | | } - | |_^ the trait `Clone` is not implemented for `B` +LL | impl Display for Cow<'_, B> { + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -15,12 +11,10 @@ LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:19:5 + --> $DIR/issue-79224.rs:18:29 | -LL | / fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { -LL | | write!(f, "foo") -LL | | } - | |_____^ the trait `Clone` is not implemented for `B` +LL | impl Display for Cow<'_, B> { + | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound diff --git a/src/test/ui/wf/issue-103573.stderr b/src/test/ui/wf/issue-103573.stderr index fcf3f15e4d3f..3b6ab3326121 100644 --- a/src/test/ui/wf/issue-103573.stderr +++ b/src/test/ui/wf/issue-103573.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied - --> $DIR/issue-103573.rs:18:5 + --> $DIR/issue-103573.rs:18:17 | LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` | help: consider further restricting the associated type | diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr index 78312a091059..b03023b5fd14 100644 --- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr +++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/wf-foreign-fn-decl-ret.rs:11:5 + --> $DIR/wf-foreign-fn-decl-ret.rs:11:25 | LL | pub fn lint_me() -> <() as Foo>::Assoc; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied --> $DIR/wf-foreign-fn-decl-ret.rs:14:32 From 0bddce50903c463ff06cc05edc1b3aba6645f50f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 03:14:27 +0000 Subject: [PATCH 217/223] Normalize assumed_wf_types after wfchecking is complete, for better spans --- compiler/rustc_hir_analysis/src/check/wfcheck.rs | 7 ++++--- src/test/ui/issues/issue-35570.stderr | 4 ++-- .../regions-implied-bounds-projection-gap-hr-1.stderr | 4 ++-- .../specialization/min_specialization/issue-79224.rs | 2 +- .../min_specialization/issue-79224.stderr | 10 +++++----- src/test/ui/traits/issue-91594.stderr | 4 ++-- src/test/ui/wf/issue-103573.stderr | 4 ++-- 7 files changed, 18 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index b663f90cab71..969f7de51ceb 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -97,21 +97,22 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>( let infcx = &tcx.infer_ctxt().build(); let ocx = ObligationCtxt::new(infcx); - let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id); - let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env }; if !tcx.features().trivial_bounds { wfcx.check_false_global_bounds() } f(&mut wfcx); + + let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id); + let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types); + let errors = wfcx.select_all_or_error(); if !errors.is_empty() { infcx.err_ctxt().report_fulfillment_errors(&errors, None); return; } - let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types); let outlives_environment = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds); diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr index b6c244241edd..2697d46bdb2f 100644 --- a/src/test/ui/issues/issue-35570.stderr +++ b/src/test/ui/issues/issue-35570.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied - --> $DIR/issue-35570.rs:8:16 + --> $DIR/issue-35570.rs:8:40 | LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 43b7b9c16b1c..6844e8665329 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied - --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:25 + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` | help: consider restricting type parameter `T` | diff --git a/src/test/ui/specialization/min_specialization/issue-79224.rs b/src/test/ui/specialization/min_specialization/issue-79224.rs index d02c108ae6bc..104bddd076ec 100644 --- a/src/test/ui/specialization/min_specialization/issue-79224.rs +++ b/src/test/ui/specialization/min_specialization/issue-79224.rs @@ -17,8 +17,8 @@ impl ToString for Cow<'_, str> { impl Display for Cow<'_, B> { //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] - //~| ERROR: the trait bound `B: Clone` is not satisfied [E0277] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + //~^ ERROR: the trait bound `B: Clone` is not satisfied [E0277] write!(f, "foo") } } diff --git a/src/test/ui/specialization/min_specialization/issue-79224.stderr b/src/test/ui/specialization/min_specialization/issue-79224.stderr index d4d7daf41117..be6f04ae62a0 100644 --- a/src/test/ui/specialization/min_specialization/issue-79224.stderr +++ b/src/test/ui/specialization/min_specialization/issue-79224.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:18:29 + --> $DIR/issue-79224.rs:18:17 | LL | impl Display for Cow<'_, B> { - | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` + | ^^^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound @@ -11,10 +11,10 @@ LL | impl Display for Cow<'_, B> { | +++++++++++++++++++ error[E0277]: the trait bound `B: Clone` is not satisfied - --> $DIR/issue-79224.rs:18:29 + --> $DIR/issue-79224.rs:20:12 | -LL | impl Display for Cow<'_, B> { - | ^^^^^^^^^^ the trait `Clone` is not implemented for `B` +LL | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + | ^^^^^ the trait `Clone` is not implemented for `B` | = note: required for `B` to implement `ToOwned` help: consider further restricting this bound diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr index 5fcd090a8349..9f9acf851135 100644 --- a/src/test/ui/traits/issue-91594.stderr +++ b/src/test/ui/traits/issue-91594.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied - --> $DIR/issue-91594.rs:10:1 + --> $DIR/issue-91594.rs:10:6 | LL | impl HasComponent<>::Interface> for Foo {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo` | = help: the trait `HasComponent<>::Interface>` is implemented for `Foo` note: required for `Foo` to implement `Component` diff --git a/src/test/ui/wf/issue-103573.stderr b/src/test/ui/wf/issue-103573.stderr index 3b6ab3326121..5227badb77dd 100644 --- a/src/test/ui/wf/issue-103573.stderr +++ b/src/test/ui/wf/issue-103573.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `<>::TypeC<'a> as TraitB>::TypeB: TraitA` is not satisfied - --> $DIR/issue-103573.rs:18:17 + --> $DIR/issue-103573.rs:18:18 | LL | fn g<'a>(_: &< as TraitB>::TypeB as TraitA>::TypeA); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TraitA` is not implemented for `<>::TypeC<'a> as TraitB>::TypeB` | help: consider further restricting the associated type | From e77e8eb9455264b70eb4344a404243b7c012db08 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 19:02:58 +0000 Subject: [PATCH 218/223] Don't store spans in assumed_wf_types actually --- compiler/rustc_middle/src/query/mod.rs | 2 +- .../src/traits/engine.rs | 6 +- compiler/rustc_ty_utils/src/implied_bounds.rs | 67 +++---------------- src/test/ui/issues/issue-35570.rs | 1 + src/test/ui/issues/issue-35570.stderr | 12 +++- ...ions-implied-bounds-projection-gap-hr-1.rs | 1 + ...-implied-bounds-projection-gap-hr-1.stderr | 17 ++++- 7 files changed, 43 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 7f794a926c06..37db2274f678 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -803,7 +803,7 @@ rustc_queries! { /// /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { + query assumed_wf_types(key: DefId) -> &'tcx ty::List> { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index 72ed3aa499da..bc6d9d4b922d 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -191,8 +191,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { let assumed_wf_types = tcx.assumed_wf_types(def_id); let mut implied_bounds = FxIndexSet::default(); let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - for &(ty, ty_span) in assumed_wf_types { - let span = if ty_span.is_dummy() { span } else { ty_span }; + let cause = ObligationCause::misc(span, hir_id); + for ty in assumed_wf_types { // FIXME(@lcnr): rustc currently does not check wf for types // pre-normalization, meaning that implied bounds are sometimes // incorrect. See #100910 for more details. @@ -205,7 +205,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { // sound and then uncomment this line again. // implied_bounds.insert(ty); - let normalized = self.normalize(&ObligationCause::misc(span, hir_id), param_env, ty); + let normalized = self.normalize(&cause, param_env, ty); implied_bounds.insert(normalized); } implied_bounds diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index e3f34373ccc9..b7a24a22c53e 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -1,80 +1,33 @@ use crate::rustc_middle::ty::DefIdTree; -use rustc_hir::{self as hir, def::DefKind, def_id::DefId}; +use rustc_hir::{def::DefKind, def_id::DefId}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::{Span, DUMMY_SP}; pub fn provide(providers: &mut ty::query::Providers) { *providers = ty::query::Providers { assumed_wf_types, ..*providers }; } -fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &[(Ty<'_>, Span)] { +fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List> { match tcx.def_kind(def_id) { DefKind::Fn => { let sig = tcx.fn_sig(def_id); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); - if let Some(node) = tcx.hir().get_if_local(def_id) - && let Some(decl) = node.fn_decl() - { - assert_eq!(decl.inputs.len(), liberated_sig.inputs().len()); - tcx.arena.alloc_from_iter(std::iter::zip( - liberated_sig.inputs_and_output, - decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]), - )) - } else { - tcx.arena.alloc_from_iter( - liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)), - ) - } + liberated_sig.inputs_and_output } DefKind::AssocFn => { let sig = tcx.fn_sig(def_id); let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig); - let assumed_wf_types = tcx.assumed_wf_types(tcx.parent(def_id)); - if let Some(node) = tcx.hir().get_if_local(def_id) - && let Some(decl) = node.fn_decl() - { - assert_eq!(decl.inputs.len(), liberated_sig.inputs().len()); - tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain(std::iter::zip( - liberated_sig.inputs_and_output, - decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]), - ))) - } else { - tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain( - liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)), - )) - } + let mut assumed_wf_types: Vec<_> = + tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into(); + assumed_wf_types.extend(liberated_sig.inputs_and_output); + tcx.intern_type_list(&assumed_wf_types) } DefKind::Impl => match tcx.impl_trait_ref(def_id) { Some(trait_ref) => { let types: Vec<_> = trait_ref.substs.types().collect(); - let self_span = if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(impl_), - .. - })) = tcx.hir().get_if_local(def_id) - { - impl_.self_ty.span - } else { - DUMMY_SP - }; - tcx.arena.alloc_from_iter(std::iter::zip( - types, - // FIXME: reliable way of getting trait ref substs... - [self_span].into_iter().chain(std::iter::repeat(DUMMY_SP)), - )) + tcx.intern_type_list(&types) } // Only the impl self type - None => { - let span = if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(impl_), - .. - })) = tcx.hir().get_if_local(def_id) - { - impl_.self_ty.span - } else { - DUMMY_SP - }; - tcx.arena.alloc_from_iter([(tcx.type_of(def_id), span)]) - } + None => tcx.intern_type_list(&[tcx.type_of(def_id)]), }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)), DefKind::Mod @@ -103,6 +56,6 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &[(Ty<'_>, Span)] { | DefKind::LifetimeParam | DefKind::GlobalAsm | DefKind::Closure - | DefKind::Generator => &[], + | DefKind::Generator => ty::List::empty(), } } diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs index 42bdb423f8f5..a2b0222d4f39 100644 --- a/src/test/ui/issues/issue-35570.rs +++ b/src/test/ui/issues/issue-35570.rs @@ -7,6 +7,7 @@ trait Trait2<'a> { fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied + //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied let _e: (usize, usize) = unsafe{mem::transmute(param)}; } diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr index 2697d46bdb2f..3dc33729d8fd 100644 --- a/src/test/ui/issues/issue-35570.stderr +++ b/src/test/ui/issues/issue-35570.stderr @@ -4,6 +4,16 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied LL | fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()` -error: aborting due to previous error +error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied + --> $DIR/issue-35570.rs:8:1 + | +LL | / fn _ice(param: Box Trait1<<() as Trait2<'a>>::Ty>>) { +LL | | +LL | | +LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)}; +LL | | } + | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs index 429548f119b1..1106352037a0 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs @@ -20,6 +20,7 @@ trait Trait2<'a, 'b> { // do not infer that. fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied { } diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index 6844e8665329..3fd39810d445 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -9,6 +9,21 @@ help: consider restricting type parameter `T` LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) | ++++++++++++++++++++++++ -error: aborting due to previous error +error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied + --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1 + | +LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) +LL | | +LL | | +LL | | { +LL | | } + | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T` + | +help: consider restricting type parameter `T` + | +LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< >::Foo >) + | ++++++++++++++++++++++++ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. From 59aa421f3518b28bba5ebc883714638e65b0a3c5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 8 Jan 2023 19:45:23 +0000 Subject: [PATCH 219/223] Suppress type errors that come from private fields --- compiler/rustc_hir_typeck/src/expr.rs | 6 +++--- src/test/ui/issues/issue-25386.rs | 1 - src/test/ui/issues/issue-25386.stderr | 8 +------- src/test/ui/privacy/private-field-ty-err.rs | 20 +++++++++++++++++++ .../ui/privacy/private-field-ty-err.stderr | 14 +++++++++++++ 5 files changed, 38 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/privacy/private-field-ty-err.rs create mode 100644 src/test/ui/privacy/private-field-ty-err.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 6ed1bc051a5f..b08b22108c8c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2217,7 +2217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.check_stability(field.did, Some(expr.hir_id), expr.span, None); return field_ty; } - private_candidate = Some((adjustments, base_def.did(), field_ty)); + private_candidate = Some((adjustments, base_def.did())); } } ty::Tuple(tys) => { @@ -2240,12 +2240,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false)); - if let Some((adjustments, did, field_ty)) = private_candidate { + if let Some((adjustments, did)) = private_candidate { // (#90483) apply adjustments to avoid ExprUseVisitor from // creating erroneous projection. self.apply_adjustments(base, adjustments); self.ban_private_field_access(expr, base_ty, field, did); - return field_ty; + return self.tcx().ty_error(); } if field.name == kw::Empty { diff --git a/src/test/ui/issues/issue-25386.rs b/src/test/ui/issues/issue-25386.rs index a76d8a615f6c..b26cc77680da 100644 --- a/src/test/ui/issues/issue-25386.rs +++ b/src/test/ui/issues/issue-25386.rs @@ -24,5 +24,4 @@ macro_rules! check_ptr_exist { fn main() { let item = stuff::Item::new(); println!("{}", check_ptr_exist!(item, name)); - //~^ ERROR field `name` of struct `CObj` is private } diff --git a/src/test/ui/issues/issue-25386.stderr b/src/test/ui/issues/issue-25386.stderr index bce269393eec..727b96908291 100644 --- a/src/test/ui/issues/issue-25386.stderr +++ b/src/test/ui/issues/issue-25386.stderr @@ -9,12 +9,6 @@ LL | println!("{}", check_ptr_exist!(item, name)); | = note: this error originates in the macro `check_ptr_exist` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0616]: field `name` of struct `CObj` is private - --> $DIR/issue-25386.rs:26:43 - | -LL | println!("{}", check_ptr_exist!(item, name)); - | ^^^^ private field - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0616`. diff --git a/src/test/ui/privacy/private-field-ty-err.rs b/src/test/ui/privacy/private-field-ty-err.rs new file mode 100644 index 000000000000..10db60695672 --- /dev/null +++ b/src/test/ui/privacy/private-field-ty-err.rs @@ -0,0 +1,20 @@ +fn main() { + let x = foo::Foo::default(); + if x.len { + //~^ ERROR field `len` of struct `Foo` is private + println!("foo"); + } +} + +mod foo { + #[derive(Default)] + pub struct Foo { + len: String, + } + + impl Foo { + pub fn len(&self) -> usize { + 42 + } + } +} diff --git a/src/test/ui/privacy/private-field-ty-err.stderr b/src/test/ui/privacy/private-field-ty-err.stderr new file mode 100644 index 000000000000..e583a25fd8fd --- /dev/null +++ b/src/test/ui/privacy/private-field-ty-err.stderr @@ -0,0 +1,14 @@ +error[E0616]: field `len` of struct `Foo` is private + --> $DIR/private-field-ty-err.rs:3:10 + | +LL | if x.len { + | ^^^ private field + | +help: a method `len` also exists, call it with parentheses + | +LL | if x.len() { + | ++ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0616`. From 65fae266eb62bc6af00b71c898b69344e25d8cd6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 8 Jan 2023 21:29:45 +0100 Subject: [PATCH 220/223] Add goml scripts to tidy checks --- src/tools/tidy/src/style.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index f409a86db26c..723a52c4c680 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -25,6 +25,7 @@ use std::path::Path; /// displayed on the console with --example. const ERROR_CODE_COLS: usize = 80; const COLS: usize = 100; +const GOML_COLS: usize = 120; const LINES: usize = 3000; @@ -230,7 +231,8 @@ pub fn check(path: &Path, bad: &mut bool) { walk(path, &mut skip, &mut |entry, contents| { let file = entry.path(); let filename = file.file_name().unwrap().to_string_lossy(); - let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"]; + let extensions = + [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl", ".goml"]; if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") { return; } @@ -255,8 +257,15 @@ pub fn check(path: &Path, bad: &mut bool) { let extension = file.extension().unwrap().to_string_lossy(); let is_error_code = extension == "md" && is_in(file, "src", "error_codes"); + let is_goml_code = extension == "goml"; - let max_columns = if is_error_code { ERROR_CODE_COLS } else { COLS }; + let max_columns = if is_error_code { + ERROR_CODE_COLS + } else if is_goml_code { + GOML_COLS + } else { + COLS + }; let can_contain = contents.contains("// ignore-tidy-") || contents.contains("# ignore-tidy-") From 31b39be9cef4f028b0a1cde5abff2f8acc426bfd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 8 Jan 2023 21:29:57 +0100 Subject: [PATCH 221/223] Fix tidy issues in goml scripts --- src/test/rustdoc-gui/escape-key.goml | 2 +- src/test/rustdoc-gui/impl-doc.goml | 6 +++--- src/test/rustdoc-gui/mobile.goml | 6 +++++- src/test/rustdoc-gui/rust-logo.goml | 21 ++++++++++++++++--- .../scrape-examples-button-focus.goml | 10 ++++----- src/test/rustdoc-gui/sidebar.goml | 2 +- .../rustdoc-gui/type-declation-overflow.goml | 1 + 7 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/test/rustdoc-gui/escape-key.goml b/src/test/rustdoc-gui/escape-key.goml index 78e9f23093ea..5d80d24969dd 100644 --- a/src/test/rustdoc-gui/escape-key.goml +++ b/src/test/rustdoc-gui/escape-key.goml @@ -5,7 +5,7 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" write: (".search-input", "test") // To be SURE that the search will be run. press-key: 'Enter' -wait-for: "#search h1" // The search element is empty before the first search +wait-for: "#search h1" // The search element is empty before the first search // Check that the currently displayed element is search. wait-for: "#alternative-display #search" assert-attribute: ("#main-content", {"class": "content hidden"}) diff --git a/src/test/rustdoc-gui/impl-doc.goml b/src/test/rustdoc-gui/impl-doc.goml index 7322032b3f5f..6caffb9c39fc 100644 --- a/src/test/rustdoc-gui/impl-doc.goml +++ b/src/test/rustdoc-gui/impl-doc.goml @@ -3,7 +3,7 @@ goto: "file://" + |DOC_PATH| + "/test_docs/struct.TypeWithImplDoc.html" // The text is about 24px tall, so if there's a margin, then their position will be >24px apart compare-elements-position-near-false: ( - "#implementations-list > .implementors-toggle > .docblock > p", - "#implementations-list > .implementors-toggle > .impl-items", - {"y": 24} + "#implementations-list > .implementors-toggle > .docblock > p", + "#implementations-list > .implementors-toggle > .impl-items", + {"y": 24} ) diff --git a/src/test/rustdoc-gui/mobile.goml b/src/test/rustdoc-gui/mobile.goml index 704542a39d21..895864d89445 100644 --- a/src/test/rustdoc-gui/mobile.goml +++ b/src/test/rustdoc-gui/mobile.goml @@ -27,4 +27,8 @@ assert-css-false: (".content .out-of-band .since::before", { "content": "\"Since goto: "file://" + |DOC_PATH| + "/settings.html" size: (400, 600) // Ignored for now https://github.com/rust-lang/rust/issues/93784. -// compare-elements-position-near-false: ("#preferred-light-theme .setting-name", "#preferred-light-theme .choice", {"y": 16}) +// compare-elements-position-near-false: ( +// "#preferred-light-theme .setting-name", +// "#preferred-light-theme .choice", +// {"y": 16}, +// ) diff --git a/src/test/rustdoc-gui/rust-logo.goml b/src/test/rustdoc-gui/rust-logo.goml index e94dc9a964dd..2d15e8b96992 100644 --- a/src/test/rustdoc-gui/rust-logo.goml +++ b/src/test/rustdoc-gui/rust-logo.goml @@ -31,13 +31,28 @@ define-function: ( call-function: ( "check-logo", - ("ayu", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"), + { + "theme": "ayu", + "filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) " + + "drop-shadow(rgb(255, 255, 255) 0px 1px 0px) " + + "drop-shadow(rgb(255, 255, 255) -1px 0px 0px) " + + "drop-shadow(rgb(255, 255, 255) 0px -1px 0px)", + }, ) call-function: ( "check-logo", - ("dark", "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px 1px 0px) drop-shadow(rgb(255, 255, 255) -1px 0px 0px) drop-shadow(rgb(255, 255, 255) 0px -1px 0px)"), + { + "theme": "dark", + "filter": "drop-shadow(rgb(255, 255, 255) 1px 0px 0px) " + + "drop-shadow(rgb(255, 255, 255) 0px 1px 0px) " + + "drop-shadow(rgb(255, 255, 255) -1px 0px 0px) " + + "drop-shadow(rgb(255, 255, 255) 0px -1px 0px)", + }, ) call-function: ( "check-logo", - ("light", "none"), + { + "theme": "light", + "filter": "none", + }, ) diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml index bba518db099a..10651a3f6696 100644 --- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml +++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml @@ -5,25 +5,25 @@ store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre focus: ".scraped-example-list > .scraped-example .next" press-key: "Enter" assert-property-false: (".scraped-example-list > .scraped-example pre", { - "scrollTop": |initialScrollTop| + "scrollTop": |initialScrollTop| }) focus: ".scraped-example-list > .scraped-example .prev" press-key: "Enter" assert-property: (".scraped-example-list > .scraped-example pre", { - "scrollTop": |initialScrollTop| + "scrollTop": |initialScrollTop| }) // The expand button increases the scrollHeight of the minimized code viewport store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight") assert-property-false: (".scraped-example-list > .scraped-example pre", { - "scrollHeight": |smallOffsetHeight| + "scrollHeight": |smallOffsetHeight| }) focus: ".scraped-example-list > .scraped-example .expand" press-key: "Enter" assert-property-false: (".scraped-example-list > .scraped-example pre", { - "offsetHeight": |smallOffsetHeight| + "offsetHeight": |smallOffsetHeight| }) store-property: (fullOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight") assert-property: (".scraped-example-list > .scraped-example pre", { - "scrollHeight": |fullOffsetHeight| + "scrollHeight": |fullOffsetHeight| }) diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml index 9db7f59695bb..9c742be0587c 100644 --- a/src/test/rustdoc-gui/sidebar.goml +++ b/src/test/rustdoc-gui/sidebar.goml @@ -148,4 +148,4 @@ assert-text: ("#toggle-all-docs", "[+]") assert-property: (".sidebar", {"clientWidth": "200"}) click: "#toggle-all-docs" assert-text: ("#toggle-all-docs", "[−]") -assert-property: (".sidebar", {"clientWidth": "200"}) \ No newline at end of file +assert-property: (".sidebar", {"clientWidth": "200"}) diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml index c014eb52e710..9b60bc04738b 100644 --- a/src/test/rustdoc-gui/type-declation-overflow.goml +++ b/src/test/rustdoc-gui/type-declation-overflow.goml @@ -1,3 +1,4 @@ +// ignore-tidy-linelength // This test ensures that the items declaration content overflow is handled inside the
 directly.
 
 // We need to disable this check because

From 6fdb54d2f103dc21197037e6b1ad0b51073b9627 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Esteban=20K=C3=BCber?= 
Date: Sun, 8 Jan 2023 22:27:13 +0000
Subject: [PATCH 222/223] Do not emit structured suggestion for turbofish with
 wrong span

Fix #79161.
---
 compiler/rustc_parse/src/parser/diagnostics.rs | 12 ++++++++++--
 src/test/ui/parser/nested-bad-turbofish.rs     |  3 +++
 src/test/ui/parser/nested-bad-turbofish.stderr | 11 +++++++++++
 3 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 src/test/ui/parser/nested-bad-turbofish.rs
 create mode 100644 src/test/ui/parser/nested-bad-turbofish.stderr

diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index b3231f55bc6e..d9fa3e31db97 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -1104,7 +1104,11 @@ impl<'a> Parser<'a> {
                     return if token::ModSep == self.token.kind {
                         // We have some certainty that this was a bad turbofish at this point.
                         // `foo< bar >::`
-                        err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        } else {
+                            err.help_turbofish = Some(());
+                        }
 
                         let snapshot = self.create_snapshot_for_diagnostic();
                         self.bump(); // `::`
@@ -1130,7 +1134,11 @@ impl<'a> Parser<'a> {
                     } else if token::OpenDelim(Delimiter::Parenthesis) == self.token.kind {
                         // We have high certainty that this was a bad turbofish at this point.
                         // `foo< bar >(`
-                        err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        if let ExprKind::Binary(o, ..) = inner_op.kind && o.node == BinOpKind::Lt {
+                            err.suggest_turbofish = Some(op.span.shrink_to_lo());
+                        } else {
+                            err.help_turbofish = Some(());
+                        }
                         // Consume the fn call arguments.
                         match self.consume_fn_args() {
                             Err(()) => Err(err.into_diagnostic(&self.sess.span_diagnostic)),
diff --git a/src/test/ui/parser/nested-bad-turbofish.rs b/src/test/ui/parser/nested-bad-turbofish.rs
new file mode 100644
index 000000000000..02099fde2121
--- /dev/null
+++ b/src/test/ui/parser/nested-bad-turbofish.rs
@@ -0,0 +1,3 @@
+fn main() {
+    foo<::V>(); //~ ERROR
+}
diff --git a/src/test/ui/parser/nested-bad-turbofish.stderr b/src/test/ui/parser/nested-bad-turbofish.stderr
new file mode 100644
index 000000000000..d82fa80e594a
--- /dev/null
+++ b/src/test/ui/parser/nested-bad-turbofish.stderr
@@ -0,0 +1,11 @@
+error: comparison operators cannot be chained
+  --> $DIR/nested-bad-turbofish.rs:2:16
+   |
+LL |     foo<::V>();
+   |                ^   ^
+   |
+   = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments
+   = help: or use `(...)` if you meant to specify fn arguments
+
+error: aborting due to previous error
+

From 8740443c354ee1510a16017fae2104fcc39933cb Mon Sep 17 00:00:00 2001
From: Ralf Jung 
Date: Mon, 9 Jan 2023 13:48:31 +0100
Subject: [PATCH 223/223] Preparing for merge from rustc

---
 src/tools/miri/rust-version | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 29f34da77eb7..cf6d9c280804 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-3b1c8a94a4e8a6ba8bc7b39cc3580db9e5b72295
+c54c8cbac882e149e04a9e1f2d146fd548ae30ae