From df8c20d7a5ddb84eb1e5fd2c366f51d357306f34 Mon Sep 17 00:00:00 2001 From: Arthur Carcano Date: Wed, 30 Oct 2024 16:40:55 +0100 Subject: [PATCH 01/16] Add intra-doc link in str::xxx_prefix --- library/core/src/str/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 89addc4cb747e..4c2d43b9edec2 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2169,7 +2169,7 @@ impl str { /// Returns a string slice with the prefix removed. /// /// If the string starts with the pattern `prefix`, returns the substring after the prefix, - /// wrapped in `Some`. Unlike `trim_start_matches`, this method removes the prefix exactly once. + /// wrapped in `Some`. Unlike [`trim_start_matches`], this method removes the prefix exactly once. /// /// If the string does not start with `prefix`, returns `None`. /// @@ -2178,6 +2178,7 @@ impl str { /// /// [`char`]: prim@char /// [pattern]: self::pattern + /// [`trim_start_matches`]: Self::trim_start_matches /// /// # Examples /// @@ -2196,7 +2197,7 @@ impl str { /// Returns a string slice with the suffix removed. /// /// If the string ends with the pattern `suffix`, returns the substring before the suffix, - /// wrapped in `Some`. Unlike `trim_end_matches`, this method removes the suffix exactly once. + /// wrapped in `Some`. Unlike [`trim_end_matches`], this method removes the suffix exactly once. /// /// If the string does not end with `suffix`, returns `None`. /// @@ -2205,6 +2206,7 @@ impl str { /// /// [`char`]: prim@char /// [pattern]: self::pattern + /// [`trim_end_matches`]: Self::trim_end_matches /// /// # Examples /// From df445264b3e97cb3e2845f6fbb9ae541225f86cf Mon Sep 17 00:00:00 2001 From: Arthur Carcano Date: Wed, 30 Oct 2024 16:50:55 +0100 Subject: [PATCH 02/16] Add intra-doc link in str::xxx_char_boundary --- library/core/src/str/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 4c2d43b9edec2..208ad9e7e5fce 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -211,7 +211,7 @@ impl str { } } - /// Finds the closest `x` not exceeding `index` where `is_char_boundary(x)` is `true`. + /// Finds the closest `x` not exceeding `index` where [`is_char_boundary(x)`] is `true`. /// /// This method can help you truncate a string so that it's still valid UTF-8, but doesn't /// exceed a given number of bytes. Note that this is done purely at the character level @@ -219,6 +219,8 @@ impl str { /// split. For example, the emoji 🧑‍🔬 (scientist) could be split so that the string only /// includes 🧑 (person) instead. /// + /// [`is_char_boundary(x)`]: Self::is_char_boundary + /// /// # Examples /// /// ``` @@ -247,7 +249,7 @@ impl str { } } - /// Finds the closest `x` not below `index` where `is_char_boundary(x)` is `true`. + /// Finds the closest `x` not below `index` where [`is_char_boundary(x)`] is `true`. /// /// If `index` is greater than the length of the string, this returns the length of the string. /// @@ -255,7 +257,7 @@ impl str { /// for more details. /// /// [`floor_char_boundary`]: str::floor_char_boundary - /// + /// [`is_char_boundary(x)`]: Self::is_char_boundary /// /// # Examples /// From 57673dd6463856c8bad426dc7508c69fa3369122 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Fri, 1 Nov 2024 22:39:08 +0900 Subject: [PATCH 03/16] Remove needless #![feature(asm_experimental_arch)] from loongarch64 inline assembly test --- tests/assembly/asm/loongarch-type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/assembly/asm/loongarch-type.rs b/tests/assembly/asm/loongarch-type.rs index 1b097f4110501..c51d35876d92d 100644 --- a/tests/assembly/asm/loongarch-type.rs +++ b/tests/assembly/asm/loongarch-type.rs @@ -3,7 +3,7 @@ //@ compile-flags: -Zmerge-functions=disabled //@ needs-llvm-components: loongarch -#![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] +#![feature(no_core, lang_items, rustc_attrs)] #![crate_type = "rlib"] #![no_core] #![allow(asm_sub_register, non_camel_case_types)] From 37db36594838d85f72e2282e73707071e80e31c0 Mon Sep 17 00:00:00 2001 From: Urgau Date: Fri, 1 Nov 2024 12:44:55 +0100 Subject: [PATCH 04/16] Also treat `impl` definition parent as transparent regarding modules --- compiler/rustc_lint/src/non_local_def.rs | 10 ++- .../convoluted-locals-132427.rs | 64 +++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 tests/ui/lint/non-local-defs/convoluted-locals-132427.rs diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 3c31b879bd6aa..3c33b2dd4789c 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -151,9 +151,15 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions { // }; // }; // ``` + // + // It isn't possible to mix a impl in a module with const-anon, but an item can + // be put inside a module and referenced by a impl so we also have to treat the + // item parent as transparent to module and for consistency we have to do the same + // for impl, otherwise the item-def and impl-def won't have the same parent. let outermost_impl_parent = peel_parent_while(cx.tcx, parent, |tcx, did| { - tcx.def_kind(did) == DefKind::Const - && tcx.opt_item_name(did) == Some(kw::Underscore) + tcx.def_kind(did) == DefKind::Mod + || (tcx.def_kind(did) == DefKind::Const + && tcx.opt_item_name(did) == Some(kw::Underscore)) }); // 2. We check if any of the paths reference a the `impl`-parent. diff --git a/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs b/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs new file mode 100644 index 0000000000000..5732e048ae38a --- /dev/null +++ b/tests/ui/lint/non-local-defs/convoluted-locals-132427.rs @@ -0,0 +1,64 @@ +// Regression tests for https://github.com/rust-lang/rust/issues/132427 + +//@ check-pass + +// original +mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; +} + +mod z { + pub enum ArbitraryContext {} + + const _: () = { + const _: () = { + impl ArbitraryContext {} + }; + }; +} + +const _: () = { + mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } +}; + +mod a { + mod b { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } +} + +mod foo { + const _: () = { + mod auth { + const _: () = { + pub enum ArbitraryContext {} + + const _: () = { + impl ArbitraryContext {} + }; + }; + } + }; +} + +fn main() {} From e1233153ac2dcc68013f9698430ac27c7abec099 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 1 Nov 2024 17:07:18 +0100 Subject: [PATCH 05/16] Move versioned LLVM target creation to rustc_codegen_ssa The OS version depends on the deployment target environment variables, the access of which we want to move to later in the compilation pipeline that has access to more information, for example `env_depinfo`. --- compiler/rustc_codegen_cranelift/src/lib.rs | 5 +- compiler/rustc_codegen_llvm/src/back/write.rs | 3 +- compiler/rustc_codegen_llvm/src/context.rs | 3 +- compiler/rustc_codegen_ssa/src/back/apple.rs | 127 ++++++++++++++++++ .../rustc_codegen_ssa/src/back/apple/tests.rs | 21 +++ compiler/rustc_codegen_ssa/src/back/link.rs | 13 +- .../rustc_codegen_ssa/src/back/metadata.rs | 10 +- compiler/rustc_codegen_ssa/src/back/mod.rs | 21 +++ compiler/rustc_driver_impl/src/lib.rs | 5 +- .../rustc_target/src/spec/base/apple/mod.rs | 123 ++--------------- .../rustc_target/src/spec/base/apple/tests.rs | 9 -- compiler/rustc_target/src/spec/mod.rs | 12 +- 12 files changed, 208 insertions(+), 144 deletions(-) create mode 100644 compiler/rustc_codegen_ssa/src/back/apple.rs create mode 100644 compiler/rustc_codegen_ssa/src/back/apple/tests.rs diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 602b1b9820023..fc3bd0abd788b 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -40,6 +40,7 @@ use std::sync::Arc; use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::CodegenResults; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::ErrorGuaranteed; @@ -260,7 +261,9 @@ impl CodegenBackend for CraneliftCodegenBackend { } fn target_triple(sess: &Session) -> target_lexicon::Triple { - match sess.target.llvm_target.parse() { + // FIXME(madsmtm): Use `sess.target.llvm_target` once target-lexicon supports unversioned macOS. + // See + match versioned_llvm_target(sess).parse() { Ok(triple) => triple, Err(err) => sess.dcx().fatal(format!("target not recognized: {}", err)), } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index bfa9e8b82a033..6b0cf95eb85f3 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -9,6 +9,7 @@ use llvm::{ LLVMRustLLVMHasZlibCompressionForDebugSymbols, LLVMRustLLVMHasZstdCompressionForDebugSymbols, }; use rustc_codegen_ssa::back::link::ensure_removed; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::back::write::{ BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn, @@ -211,7 +212,7 @@ pub(crate) fn target_machine_factory( singlethread = false; } - let triple = SmallCStr::new(&sess.target.llvm_target); + let triple = SmallCStr::new(&versioned_llvm_target(sess)); let cpu = SmallCStr::new(llvm_util::target_cpu(sess)); let features = CString::new(target_features.join(",")).unwrap(); let abi = SmallCStr::new(&sess.target.llvm_abiname); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 313957dda9642..97a9f9c60e3d2 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use std::ffi::{CStr, c_uint}; use std::str; +use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::errors as ssa_errors; use rustc_codegen_ssa::traits::*; @@ -177,7 +178,7 @@ pub(crate) unsafe fn create_module<'ll>( llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); } - let llvm_target = SmallCStr::new(&sess.target.llvm_target); + let llvm_target = SmallCStr::new(&versioned_llvm_target(sess)); unsafe { llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); } diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs new file mode 100644 index 0000000000000..939ce2e1a03ad --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -0,0 +1,127 @@ +use std::env; +use std::num::ParseIntError; + +use rustc_session::Session; +use rustc_target::spec::Target; + +#[cfg(test)] +mod tests; + +/// Deployment target or SDK version. +/// +/// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. +type OSVersion = (u16, u8, u8); + +/// Parse an OS version triple (SDK version or deployment target). +fn parse_version(version: &str) -> Result { + if let Some((major, minor)) = version.split_once('.') { + let major = major.parse()?; + if let Some((minor, patch)) = minor.split_once('.') { + Ok((major, minor.parse()?, patch.parse()?)) + } else { + Ok((major, minor.parse()?, 0)) + } + } else { + Ok((version.parse()?, 0, 0)) + } +} + +/// Minimum operating system versions currently supported by `rustc`. +fn os_minimum_deployment_target(os: &str) -> OSVersion { + // When bumping a version in here, remember to update the platform-support docs too. + // + // NOTE: The defaults may change in future `rustc` versions, so if you are looking for the + // default deployment target, prefer: + // ``` + // $ rustc --print deployment-target + // ``` + match os { + "macos" => (10, 12, 0), + "ios" => (10, 0, 0), + "tvos" => (10, 0, 0), + "watchos" => (5, 0, 0), + "visionos" => (1, 0, 0), + _ => unreachable!("tried to get deployment target for non-Apple platform"), + } +} + +/// The deployment target for the given target. +/// +/// This is similar to `os_minimum_deployment_target`, except that on certain targets it makes sense +/// to raise the minimum OS version. +/// +/// This matches what LLVM does, see in part: +/// +fn minimum_deployment_target(target: &Target) -> OSVersion { + match (&*target.os, &*target.arch, &*target.abi) { + ("macos", "aarch64", _) => (11, 0, 0), + ("ios", "aarch64", "macabi") => (14, 0, 0), + ("ios", "aarch64", "sim") => (14, 0, 0), + ("ios", _, _) if target.llvm_target.starts_with("arm64e") => (14, 0, 0), + // Mac Catalyst defaults to 13.1 in Clang. + ("ios", _, "macabi") => (13, 1, 0), + ("tvos", "aarch64", "sim") => (14, 0, 0), + ("watchos", "aarch64", "sim") => (7, 0, 0), + (os, _, _) => os_minimum_deployment_target(os), + } +} + +/// Name of the environment variable used to fetch the deployment target on the given OS. +fn deployment_target_env_var(os: &str) -> &'static str { + match os { + "macos" => "MACOSX_DEPLOYMENT_TARGET", + "ios" => "IPHONEOS_DEPLOYMENT_TARGET", + "watchos" => "WATCHOS_DEPLOYMENT_TARGET", + "tvos" => "TVOS_DEPLOYMENT_TARGET", + "visionos" => "XROS_DEPLOYMENT_TARGET", + _ => unreachable!("tried to get deployment target env var for non-Apple platform"), + } +} + +/// Get the deployment target based on the standard environment variables, or fall back to the +/// minimum version supported by `rustc`. +pub fn deployment_target(sess: &Session) -> OSVersion { + let min = minimum_deployment_target(&sess.target); + + if let Ok(deployment_target) = env::var(deployment_target_env_var(&sess.target.os)) { + match parse_version(&deployment_target) { + // It is common that the deployment target is set too low, e.g. on macOS Aarch64 to also + // target older x86_64, the user may set a lower deployment target than supported. + // + // To avoid such issues, we silently raise the deployment target here. + // FIXME: We want to show a warning when `version < os_min`. + Ok(version) => version.max(min), + // FIXME: Report erroneous environment variable to user. + Err(_) => min, + } + } else { + // If no deployment target variable is set, default to the minimum found above. + min + } +} + +pub(super) fn add_version_to_llvm_target( + llvm_target: &str, + deployment_target: OSVersion, +) -> String { + let mut components = llvm_target.split("-"); + let arch = components.next().expect("apple target should have arch"); + let vendor = components.next().expect("apple target should have vendor"); + let os = components.next().expect("apple target should have os"); + let environment = components.next(); + assert_eq!(components.next(), None, "too many LLVM triple components"); + + let (major, minor, patch) = deployment_target; + + assert!( + !os.contains(|c: char| c.is_ascii_digit()), + "LLVM target must not already be versioned" + ); + + if let Some(env) = environment { + // Insert version into OS, before environment + format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}-{env}") + } else { + format!("{arch}-{vendor}-{os}{major}.{minor}.{patch}") + } +} diff --git a/compiler/rustc_codegen_ssa/src/back/apple/tests.rs b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs new file mode 100644 index 0000000000000..7ccda5a8190c7 --- /dev/null +++ b/compiler/rustc_codegen_ssa/src/back/apple/tests.rs @@ -0,0 +1,21 @@ +use super::{add_version_to_llvm_target, parse_version}; + +#[test] +fn test_add_version_to_llvm_target() { + assert_eq!( + add_version_to_llvm_target("aarch64-apple-macosx", (10, 14, 1)), + "aarch64-apple-macosx10.14.1" + ); + assert_eq!( + add_version_to_llvm_target("aarch64-apple-ios-simulator", (16, 1, 0)), + "aarch64-apple-ios16.1.0-simulator" + ); +} + +#[test] +fn test_parse_version() { + assert_eq!(parse_version("10"), Ok((10, 0, 0))); + assert_eq!(parse_version("10.12"), Ok((10, 12, 0))); + assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); + assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); +} diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 34dc599e4fddd..b01a62b394b52 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -40,7 +40,7 @@ use rustc_target::spec::crt_objects::CrtObjects; use rustc_target::spec::{ Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault, LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, - SplitDebuginfo, current_apple_deployment_target, + SplitDebuginfo, }; use tempfile::Builder as TempFileBuilder; use tracing::{debug, info, warn}; @@ -50,6 +50,7 @@ use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; use super::rpath::{self, RPathConfig}; +use super::{apple, versioned_llvm_target}; use crate::{ CodegenResults, CompiledModule, CrateInfo, NativeLib, common, errors, looks_like_rust_object_file, @@ -2447,7 +2448,7 @@ fn add_order_independent_options( if flavor == LinkerFlavor::Llbc { cmd.link_args(&[ "--target", - sess.target.llvm_target.as_ref(), + &versioned_llvm_target(sess), "--target-cpu", &codegen_results.crate_info.target_cpu, ]); @@ -3039,7 +3040,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"), }; - let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let (major, minor, patch) = apple::deployment_target(sess); let min_version = format!("{major}.{minor}.{patch}"); // The SDK version is used at runtime when compiling with a newer SDK / version of Xcode: @@ -3109,7 +3110,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // The presence of `-mmacosx-version-min` makes CC default to // macOS, and it sets the deployment target. - let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let (major, minor, patch) = apple::deployment_target(sess); // Intentionally pass this as a single argument, Clang doesn't // seem to like it otherwise. cmd.cc_arg(&format!("-mmacosx-version-min={major}.{minor}.{patch}")); @@ -3119,7 +3120,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo // // We avoid `-m32`/`-m64`, as this is already encoded by `-arch`. } else { - cmd.cc_args(&["-target", &sess.target.llvm_target]); + cmd.cc_args(&["-target", &versioned_llvm_target(sess)]); } } } @@ -3345,7 +3346,7 @@ fn add_lld_args( // 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.cc_arg(format!("--target={}", sess.target.llvm_target)); + cmd.cc_arg(format!("--target={}", versioned_llvm_target(sess))); } } } diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 4c25c85569b5d..1b11fe661dbaf 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -22,6 +22,8 @@ use rustc_span::sym; use rustc_target::abi::Endian; use rustc_target::spec::{RelocModel, Target, ef_avr_arch}; +use super::apple; + /// The default metadata loader. This is used by cg_llvm and cg_clif. /// /// # Metadata location @@ -238,7 +240,7 @@ pub(crate) fn create_object_file(sess: &Session) -> Option Option object::write::MachOBuildVersion { +fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachOBuildVersion { /// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz" /// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200 fn pack_version((major, minor, patch): (u16, u8, u8)) -> u32 { @@ -401,8 +403,8 @@ fn macho_object_build_version_for_target(target: &Target) -> object::write::Mach } let platform = - rustc_target::spec::current_apple_platform(target).expect("unknown Apple target OS"); - let min_os = rustc_target::spec::current_apple_deployment_target(target); + rustc_target::spec::current_apple_platform(&sess.target).expect("unknown Apple target OS"); + let min_os = apple::deployment_target(sess); let mut build_version = object::write::MachOBuildVersion::default(); build_version.platform = platform; diff --git a/compiler/rustc_codegen_ssa/src/back/mod.rs b/compiler/rustc_codegen_ssa/src/back/mod.rs index 2b3a2e3a369bb..64b5d4569ecce 100644 --- a/compiler/rustc_codegen_ssa/src/back/mod.rs +++ b/compiler/rustc_codegen_ssa/src/back/mod.rs @@ -1,3 +1,8 @@ +use std::borrow::Cow; + +use rustc_session::Session; + +pub mod apple; pub mod archive; pub(crate) mod command; pub mod link; @@ -7,3 +12,19 @@ pub mod metadata; pub(crate) mod rpath; pub mod symbol_export; pub mod write; + +/// The target triple depends on the deployment target, and is required to +/// enable features such as cross-language LTO, and for picking the right +/// Mach-O commands. +/// +/// Certain optimizations also depend on the deployment target. +pub fn versioned_llvm_target(sess: &Session) -> Cow<'_, str> { + if sess.target.is_like_osx { + apple::add_version_to_llvm_target(&sess.target.llvm_target, apple::deployment_target(sess)) + .into() + } else { + // FIXME(madsmtm): Certain other targets also include a version, + // we might want to move that here as well. + Cow::Borrowed(&sess.target.llvm_target) + } +} diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e2585c023883a..06b4c89946d93 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -33,6 +33,7 @@ use std::time::{Instant, SystemTime}; use std::{env, str}; use rustc_ast as ast; +use rustc_codegen_ssa::back::apple; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CodegenErrors, CodegenResults}; use rustc_data_structures::profiling::{ @@ -855,10 +856,8 @@ fn print_crate_info( } } DeploymentTarget => { - use rustc_target::spec::current_apple_deployment_target; - if sess.target.is_like_osx { - let (major, minor, patch) = current_apple_deployment_target(&sess.target); + let (major, minor, patch) = apple::deployment_target(sess); let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; println_info!("deployment_target={major}.{minor}{patch}") } else { diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 73763cf034ca0..837af954a0708 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; use std::env; -use std::num::ParseIntError; use crate::spec::{ Cc, DebuginfoKind, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType, StaticCow, @@ -97,9 +96,8 @@ impl TargetAbi { } } -/// Get the base target options, LLVM target and `target_arch` from the three -/// things that uniquely identify Rust's Apple targets: The OS, the -/// architecture, and the ABI. +/// Get the base target options, unversioned LLVM target and `target_arch` from the three +/// things that uniquely identify Rust's Apple targets: The OS, the architecture, and the ABI. pub(crate) fn base( os: &'static str, arch: Arch, @@ -155,7 +153,7 @@ pub(crate) fn base( ..Default::default() }; - (opts, llvm_target(os, arch, abi), arch.target_arch()) + (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch()) } pub fn platform(target: &Target) -> Option { @@ -175,97 +173,11 @@ pub fn platform(target: &Target) -> Option { }) } -/// Hack for calling `deployment_target` outside of this module. -pub fn deployment_target_for_target(target: &Target) -> (u16, u8, u8) { - let arch = if target.llvm_target.starts_with("arm64e") { - Arch::Arm64e - } else if target.arch == "aarch64" { - Arch::Arm64 - } else { - // Dummy architecture, only used by `deployment_target` anyhow - Arch::X86_64 - }; - let abi = match &*target.abi { - "macabi" => TargetAbi::MacCatalyst, - "sim" => TargetAbi::Simulator, - "" => TargetAbi::Normal, - abi => unreachable!("invalid abi '{abi}' for Apple target"), - }; - deployment_target(&target.os, arch, abi) -} - -/// Get the deployment target based on the standard environment variables, or -/// fall back to a sane default. -fn deployment_target(os: &str, arch: Arch, abi: TargetAbi) -> (u16, u8, u8) { - // When bumping a version in here, remember to update the platform-support - // docs too. - // - // NOTE: If you are looking for the default deployment target, prefer - // `rustc --print deployment-target`, as the default here may change in - // future `rustc` versions. - - // Minimum operating system versions currently supported by `rustc`. - let os_min = match os { - "macos" => (10, 12, 0), - "ios" => (10, 0, 0), - "tvos" => (10, 0, 0), - "watchos" => (5, 0, 0), - "visionos" => (1, 0, 0), - _ => unreachable!("tried to get deployment target for non-Apple platform"), - }; - - // On certain targets it makes sense to raise the minimum OS version. - // - // This matches what LLVM does, see: - // - let min = match (os, arch, abi) { - ("macos", Arch::Arm64 | Arch::Arm64e, _) => (11, 0, 0), - ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::MacCatalyst) => (14, 0, 0), - ("ios", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), - ("ios", Arch::Arm64e, TargetAbi::Normal) => (14, 0, 0), - // Mac Catalyst defaults to 13.1 in Clang. - ("ios", _, TargetAbi::MacCatalyst) => (13, 1, 0), - ("tvos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (14, 0, 0), - ("watchos", Arch::Arm64 | Arch::Arm64e, TargetAbi::Simulator) => (7, 0, 0), - _ => os_min, - }; - - // The environment variable used to fetch the deployment target. - let env_var = match os { - "macos" => "MACOSX_DEPLOYMENT_TARGET", - "ios" => "IPHONEOS_DEPLOYMENT_TARGET", - "watchos" => "WATCHOS_DEPLOYMENT_TARGET", - "tvos" => "TVOS_DEPLOYMENT_TARGET", - "visionos" => "XROS_DEPLOYMENT_TARGET", - _ => unreachable!("tried to get deployment target env var for non-Apple platform"), - }; - - if let Ok(deployment_target) = env::var(env_var) { - match parse_version(&deployment_target) { - // It is common that the deployment target is set too low, e.g. on - // macOS Aarch64 to also target older x86_64, the user may set a - // lower deployment target than supported. - // - // To avoid such issues, we silently raise the deployment target - // here. - // FIXME: We want to show a warning when `version < os_min`. - Ok(version) => version.max(min), - // FIXME: Report erroneous environment variable to user. - Err(_) => min, - } - } else { - min - } -} - -/// Generate the target triple that we need to pass to LLVM and/or Clang. -fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { - // The target triple depends on the deployment target, and is required to - // enable features such as cross-language LTO, and for picking the right - // Mach-O commands. - // - // Certain optimizations also depend on the deployment target. - let (major, minor, patch) = deployment_target(os, arch, abi); +/// Generate part of the LLVM target triple. +/// +/// See `rustc_codegen_ssa::back::versioned_llvm_target` for the full triple passed to LLVM and +/// Clang. +fn unversioned_llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { let arch = arch.target_name(); // Convert to the "canonical" OS name used by LLVM: // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282 @@ -282,7 +194,7 @@ fn llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow { TargetAbi::MacCatalyst => "-macabi", TargetAbi::Simulator => "-simulator", }; - format!("{arch}-apple-{os}{major}.{minor}.{patch}{environment}").into() + format!("{arch}-apple-{os}{environment}").into() } fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { @@ -321,20 +233,3 @@ fn link_env_remove(os: &'static str) -> StaticCow<[StaticCow]> { cvs!["MACOSX_DEPLOYMENT_TARGET"] } } - -/// Parse an OS version triple (SDK version or deployment target). -/// -/// The size of the returned numbers here are limited by Mach-O's -/// `LC_BUILD_VERSION`. -fn parse_version(version: &str) -> Result<(u16, u8, u8), ParseIntError> { - if let Some((major, minor)) = version.split_once('.') { - let major = major.parse()?; - if let Some((minor, patch)) = minor.split_once('.') { - Ok((major, minor.parse()?, patch.parse()?)) - } else { - Ok((major, minor.parse()?, 0)) - } - } else { - Ok((version.parse()?, 0, 0)) - } -} diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs index 9435b9a5bad59..a7335c9bcaed4 100644 --- a/compiler/rustc_target/src/spec/base/apple/tests.rs +++ b/compiler/rustc_target/src/spec/base/apple/tests.rs @@ -1,4 +1,3 @@ -use super::parse_version; use crate::spec::targets::{ aarch64_apple_darwin, aarch64_apple_ios_sim, aarch64_apple_visionos_sim, aarch64_apple_watchos_sim, i686_apple_darwin, x86_64_apple_darwin, x86_64_apple_ios, @@ -40,11 +39,3 @@ fn macos_link_environment_unmodified() { ],); } } - -#[test] -fn test_parse_version() { - assert_eq!(parse_version("10"), Ok((10, 0, 0))); - assert_eq!(parse_version("10.12"), Ok((10, 12, 0))); - assert_eq!(parse_version("10.12.6"), Ok((10, 12, 6))); - assert_eq!(parse_version("9999.99.99"), Ok((9999, 99, 99))); -} diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f4cbe47e0f352..1265cc3454970 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -59,10 +59,7 @@ pub mod abi; pub mod crt_objects; mod base; -pub use base::apple::{ - deployment_target_for_target as current_apple_deployment_target, - platform as current_apple_platform, -}; +pub use base::apple::platform as current_apple_platform; pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. @@ -2003,7 +2000,12 @@ impl TargetWarnings { /// Every field here must be specified, and has no default value. #[derive(PartialEq, Clone, Debug)] pub struct Target { - /// Target triple to pass to LLVM. + /// Unversioned target triple to pass to LLVM. + /// + /// Target triples can optionally contain an OS version (notably Apple targets), which rustc + /// cannot know without querying the environment. + /// + /// Use `rustc_codegen_ssa::back::versioned_llvm_target` if you need the full LLVM target. pub llvm_target: StaticCow, /// Metadata about a target, for example the description or tier. /// Used for generating target documentation. From e75a7ddad37feea205df1e4b568a5316b31da641 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 1 Nov 2024 17:05:10 +0100 Subject: [PATCH 06/16] Move Mach-O platform information to rustc_codegen_ssa::back::apple To align with the general decision to have this sort of information there instead. Also use the visionOS values added in newer `object` release. --- compiler/rustc_codegen_ssa/src/back/apple.rs | 16 ++++++++++++++++ .../rustc_codegen_ssa/src/back/metadata.rs | 3 +-- .../rustc_target/src/spec/base/apple/mod.rs | 19 +------------------ compiler/rustc_target/src/spec/mod.rs | 1 - 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 939ce2e1a03ad..23460ae9e1e25 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -7,6 +7,22 @@ use rustc_target::spec::Target; #[cfg(test)] mod tests; +pub(super) fn macho_platform(target: &Target) -> u32 { + match (&*target.os, &*target.abi) { + ("macos", _) => object::macho::PLATFORM_MACOS, + ("ios", "macabi") => object::macho::PLATFORM_MACCATALYST, + ("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR, + ("ios", _) => object::macho::PLATFORM_IOS, + ("watchos", "sim") => object::macho::PLATFORM_WATCHOSSIMULATOR, + ("watchos", _) => object::macho::PLATFORM_WATCHOS, + ("tvos", "sim") => object::macho::PLATFORM_TVOSSIMULATOR, + ("tvos", _) => object::macho::PLATFORM_TVOS, + ("visionos", "sim") => object::macho::PLATFORM_XROSSIMULATOR, + ("visionos", _) => object::macho::PLATFORM_XROS, + _ => unreachable!("tried to get Mach-O platform for non-Apple target"), + } +} + /// Deployment target or SDK version. /// /// The size of the numbers in here are limited by Mach-O's `LC_BUILD_VERSION`. diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs index 1b11fe661dbaf..5544f8d40c9f3 100644 --- a/compiler/rustc_codegen_ssa/src/back/metadata.rs +++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs @@ -402,8 +402,7 @@ fn macho_object_build_version_for_target(sess: &Session) -> object::write::MachO (major << 16) | (minor << 8) | patch } - let platform = - rustc_target::spec::current_apple_platform(&sess.target).expect("unknown Apple target OS"); + let platform = apple::macho_platform(&sess.target); let min_os = apple::deployment_target(sess); let mut build_version = object::write::MachOBuildVersion::default(); diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 837af954a0708..f45c86640936f 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -3,7 +3,7 @@ use std::env; use crate::spec::{ Cc, DebuginfoKind, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType, StaticCow, - Target, TargetOptions, cvs, + TargetOptions, cvs, }; #[cfg(test)] @@ -156,23 +156,6 @@ pub(crate) fn base( (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch()) } -pub fn platform(target: &Target) -> Option { - Some(match (&*target.os, &*target.abi) { - ("macos", _) => object::macho::PLATFORM_MACOS, - ("ios", "macabi") => object::macho::PLATFORM_MACCATALYST, - ("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR, - ("ios", _) => object::macho::PLATFORM_IOS, - ("watchos", "sim") => object::macho::PLATFORM_WATCHOSSIMULATOR, - ("watchos", _) => object::macho::PLATFORM_WATCHOS, - ("tvos", "sim") => object::macho::PLATFORM_TVOSSIMULATOR, - ("tvos", _) => object::macho::PLATFORM_TVOS, - // FIXME: Upgrade to `object-rs` 0.33+ implementation with visionOS platform definition - ("visionos", "sim") => 12, - ("visionos", _) => 11, - _ => return None, - }) -} - /// Generate part of the LLVM target triple. /// /// See `rustc_codegen_ssa::back::versioned_llvm_target` for the full triple passed to LLVM and diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 1265cc3454970..a5bc90477b323 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -59,7 +59,6 @@ pub mod abi; pub mod crt_objects; mod base; -pub use base::apple::platform as current_apple_platform; pub use base::avr_gnu::ef_avr_arch; /// Linker is called through a C/C++ compiler. From 1ef1af1c607fe268b5622041ff586ca603b8ec8d Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 29 Sep 2024 22:14:55 +0200 Subject: [PATCH 07/16] Emit diagnostics for incorrect deployment targets --- compiler/rustc_codegen_ssa/messages.ftl | 6 +++ compiler/rustc_codegen_ssa/src/back/apple.rs | 46 ++++++++++++++++---- compiler/rustc_codegen_ssa/src/errors.rs | 9 ++++ compiler/rustc_codegen_ssa/src/lib.rs | 1 + compiler/rustc_driver_impl/src/lib.rs | 7 +-- 5 files changed, 57 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index d07274920feaf..3b34eb063ec04 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -2,6 +2,12 @@ codegen_ssa_L4Bender_exporting_symbols_unimplemented = exporting symbols not imp codegen_ssa_add_native_library = failed to add native library {$library_path}: {$error} +codegen_ssa_apple_deployment_target_invalid = + failed to parse deployment target specified in {$env_var}: {$error} + +codegen_ssa_apple_deployment_target_too_low = + deployment target in {$env_var} was set to {$version}, but the minimum supported by `rustc` is {$os_min} + codegen_ssa_apple_sdk_error_sdk_path = failed to get {$sdk_name} SDK path: {$error} codegen_ssa_archive_build_failure = failed to build archive at `{$path}`: {$error} diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs index 23460ae9e1e25..93d90cd16b24a 100644 --- a/compiler/rustc_codegen_ssa/src/back/apple.rs +++ b/compiler/rustc_codegen_ssa/src/back/apple.rs @@ -1,9 +1,12 @@ use std::env; +use std::fmt::{Display, from_fn}; use std::num::ParseIntError; use rustc_session::Session; use rustc_target::spec::Target; +use crate::errors::AppleDeploymentTarget; + #[cfg(test)] mod tests; @@ -42,6 +45,17 @@ fn parse_version(version: &str) -> Result { } } +pub fn pretty_version(version: OSVersion) -> impl Display { + let (major, minor, patch) = version; + from_fn(move |f| { + write!(f, "{major}.{minor}")?; + if patch != 0 { + write!(f, ".{patch}")?; + } + Ok(()) + }) +} + /// Minimum operating system versions currently supported by `rustc`. fn os_minimum_deployment_target(os: &str) -> OSVersion { // When bumping a version in here, remember to update the platform-support docs too. @@ -98,17 +112,31 @@ fn deployment_target_env_var(os: &str) -> &'static str { /// minimum version supported by `rustc`. pub fn deployment_target(sess: &Session) -> OSVersion { let min = minimum_deployment_target(&sess.target); + let env_var = deployment_target_env_var(&sess.target.os); - if let Ok(deployment_target) = env::var(deployment_target_env_var(&sess.target.os)) { + if let Ok(deployment_target) = env::var(env_var) { match parse_version(&deployment_target) { - // It is common that the deployment target is set too low, e.g. on macOS Aarch64 to also - // target older x86_64, the user may set a lower deployment target than supported. - // - // To avoid such issues, we silently raise the deployment target here. - // FIXME: We want to show a warning when `version < os_min`. - Ok(version) => version.max(min), - // FIXME: Report erroneous environment variable to user. - Err(_) => min, + Ok(version) => { + let os_min = os_minimum_deployment_target(&sess.target.os); + // It is common that the deployment target is set a bit too low, for example on + // macOS Aarch64 to also target older x86_64. So we only want to warn when variable + // is lower than the minimum OS supported by rustc, not when the variable is lower + // than the minimum for a specific target. + if version < os_min { + sess.dcx().emit_warn(AppleDeploymentTarget::TooLow { + env_var, + version: pretty_version(version).to_string(), + os_min: pretty_version(os_min).to_string(), + }); + } + + // Raise the deployment target to the minimum supported. + version.max(min) + } + Err(error) => { + sess.dcx().emit_err(AppleDeploymentTarget::Invalid { env_var, error }); + min + } } } else { // If no deployment target variable is set, default to the minimum found above. diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index d67cf0e3a6d5f..cf8d1cfa0d10e 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::io::Error; +use std::num::ParseIntError; use std::path::{Path, PathBuf}; use std::process::ExitStatus; @@ -539,6 +540,14 @@ pub(crate) struct UnsupportedArch<'a> { pub os: &'a str, } +#[derive(Diagnostic)] +pub(crate) enum AppleDeploymentTarget { + #[diag(codegen_ssa_apple_deployment_target_invalid)] + Invalid { env_var: &'static str, error: ParseIntError }, + #[diag(codegen_ssa_apple_deployment_target_too_low)] + TooLow { env_var: &'static str, version: String, os_min: String }, +} + #[derive(Diagnostic)] pub(crate) enum AppleSdkRootError<'a> { #[diag(codegen_ssa_apple_sdk_error_sdk_path)] diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 73bfa9dbd10e2..7dc8ab38a9764 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(assert_matches)] #![feature(box_patterns)] +#![feature(debug_closure_helpers)] #![feature(file_buffered)] #![feature(if_let_guard)] #![feature(let_chains)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 06b4c89946d93..92b622fccf26a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -857,9 +857,10 @@ fn print_crate_info( } DeploymentTarget => { if sess.target.is_like_osx { - let (major, minor, patch) = apple::deployment_target(sess); - let patch = if patch != 0 { format!(".{patch}") } else { String::new() }; - println_info!("deployment_target={major}.{minor}{patch}") + println_info!( + "deployment_target={}", + apple::pretty_version(apple::deployment_target(sess)) + ) } else { #[allow(rustc::diagnostic_outside_of_impl)] sess.dcx().fatal("only Apple targets currently support deployment version info") From 075f197379116ebfd44755714210221b8e9e70e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 24 Oct 2024 22:16:43 +0000 Subject: [PATCH 08/16] Add trait diff highlighting logic and use it in E0277 When a trait is not implemented for a type, but there *is* an `impl` for another type or different trait params, we format the output to use highlighting in the same way that E0308 does for types. The logic accounts for 3 cases: - When both the type and trait in the expected predicate and the candidate are different - When only the types are different - When only the trait generic params are different For each case, we use slightly different formatting and wording. --- .../src/error_reporting/infer/mod.rs | 61 +++++++++++++++++ .../traits/fulfillment_errors.rs | 68 +++++++++++++++---- .../associated-type-bound-fail.stderr | 3 +- .../defaults/rp_impl_trait_fail.stderr | 6 +- .../defaults/trait_objects_fail.stderr | 6 +- .../ui/const-generics/defaults/wfness.stderr | 6 +- .../occurs-check/unused-substs-1.stderr | 3 +- .../as_expression.current.stderr | 3 +- .../as_expression.next.stderr | 3 +- .../unsatisfied-bounds.stderr | 6 +- ...between-expected-trait-and-found-trait.svg | 28 ++++---- .../return-dont-satisfy-bounds.stderr | 3 +- tests/ui/impl-trait/issues/issue-62742.stderr | 6 +- tests/ui/impl-trait/nested-rpit-hrtb.stderr | 6 +- tests/ui/indexing/index-help.stderr | 3 +- .../indexing/indexing-requires-a-uint.stderr | 3 +- ...int-at-index-for-obligation-failure.stderr | 3 +- tests/ui/integral-indexing.stderr | 24 ++++--- tests/ui/issues/issue-34334.stderr | 3 +- tests/ui/issues/issue-45801.stderr | 3 +- ...e-66923-show-error-for-correct-call.stderr | 6 +- .../invalid-iterator-chain-fixable.stderr | 6 +- .../iterators/invalid-iterator-chain.stderr | 6 +- ...er_breaking_with_unit_fallback.unit.stderr | 3 +- ...lue-fallback-issue-66757.nofallback.stderr | 3 +- tests/ui/on-unimplemented/impl-substs.stderr | 3 +- tests/ui/on-unimplemented/on-impl.stderr | 6 +- tests/ui/on-unimplemented/slice-index.stderr | 3 +- tests/ui/str/str-idx.stderr | 9 ++- tests/ui/str/str-mut-idx.stderr | 9 ++- tests/ui/suggestions/issue-101623.stderr | 3 +- .../suggest-dereferencing-index.stderr | 3 +- tests/ui/traits/coercion-generic-bad.stderr | 3 +- tests/ui/traits/negative-bounds/simple.stderr | 3 +- tests/ui/try-block/try-block-bad-type.stderr | 3 +- tests/ui/try-trait/bad-interconversion.stderr | 9 ++- .../constrain_in_projection.current.stderr | 3 +- .../nested-tait-inference.current.stderr | 3 +- .../self-referential-2.current.stderr | 3 +- ...t-similar-impls-for-root-obligation.stderr | 3 +- 40 files changed, 251 insertions(+), 86 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 574cf1e88b16b..4725047090edf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -766,6 +766,67 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { values } + pub fn cmp_traits( + &self, + def_id1: DefId, + args1: &[ty::GenericArg<'tcx>], + def_id2: DefId, + args2: &[ty::GenericArg<'tcx>], + ) -> (DiagStyledString, DiagStyledString) { + let mut values = (DiagStyledString::new(), DiagStyledString::new()); + + if def_id1 != def_id2 { + values.0.push_highlighted(self.tcx.def_path_str(def_id1).as_str()); + values.1.push_highlighted(self.tcx.def_path_str(def_id2).as_str()); + } else { + values.0.push_normal(self.tcx.item_name(def_id1).as_str()); + values.1.push_normal(self.tcx.item_name(def_id2).as_str()); + } + + if args1.len() != args2.len() { + let (pre, post) = if args1.len() > 0 { ("<", ">") } else { ("", "") }; + values.0.push_normal(format!( + "{pre}{}{post}", + args1.iter().map(|a| a.to_string()).collect::>().join(", ") + )); + let (pre, post) = if args2.len() > 0 { ("<", ">") } else { ("", "") }; + values.1.push_normal(format!( + "{pre}{}{post}", + args2.iter().map(|a| a.to_string()).collect::>().join(", ") + )); + return values; + } + + if args1.len() > 0 { + values.0.push_normal("<"); + values.1.push_normal("<"); + } + for (i, (a, b)) in std::iter::zip(args1, args2).enumerate() { + let a_str = a.to_string(); + let b_str = b.to_string(); + if let (Some(a), Some(b)) = (a.as_type(), b.as_type()) { + let (a, b) = self.cmp(a, b); + values.0.0.extend(a.0); + values.1.0.extend(b.0); + } else if a_str != b_str { + values.0.push_highlighted(a_str); + values.1.push_highlighted(b_str); + } else { + values.0.push_normal(a_str); + values.1.push_normal(b_str); + } + if i + 1 < args1.len() { + values.0.push_normal(", "); + values.1.push_normal(", "); + } + } + if args1.len() > 0 { + values.0.push_normal(">"); + values.1.push_normal(">"); + } + values + } + /// Compares two given types, eliding parts that are the same between them and highlighting /// relevant differences, and return two representation of those types for highlighted printing. pub fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagStyledString, DiagStyledString) { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 7aa558cfd3ffe..358c244eca941 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1832,21 +1832,63 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if impl_trait_ref.references_error() { return false; } - let self_ty = impl_trait_ref.self_ty().to_string(); - err.highlighted_help(vec![ - StringPart::normal(format!( - "the trait `{}` ", - impl_trait_ref.print_trait_sugared() - )), - StringPart::highlighted("is"), + + let traits = self.cmp_traits( + obligation_trait_ref.def_id, + &obligation_trait_ref.args[1..], + impl_trait_ref.def_id, + &impl_trait_ref.args[1..], + ); + let traits_content = (traits.0.content(), traits.1.content()); + let types = self.cmp(obligation_trait_ref.self_ty(), impl_trait_ref.self_ty()); + let types_content = (types.0.content(), types.1.content()); + let mut msg = vec![StringPart::normal("the trait `")]; + if traits_content.0 == traits_content.1 { + msg.push(StringPart::normal( + impl_trait_ref.print_trait_sugared().to_string(), + )); + } else { + msg.extend(traits.0.0); + } + msg.extend([ + StringPart::normal("` "), + StringPart::highlighted("is not"), StringPart::normal(" implemented for `"), - if let [TypeError::Sorts(_)] = &terrs[..] { - StringPart::normal(self_ty) - } else { - StringPart::highlighted(self_ty) - }, - StringPart::normal("`"), ]); + if types_content.0 == types_content.1 { + msg.push(StringPart::normal(obligation_trait_ref.self_ty().to_string())); + } else { + msg.extend(types.0.0); + } + msg.push(StringPart::normal("`")); + if types_content.0 == types_content.1 { + msg.push(StringPart::normal("\nbut trait `")); + msg.extend(traits.1.0); + msg.extend([ + StringPart::normal("` "), + StringPart::highlighted("is"), + StringPart::normal(" implemented for it"), + ]); + } else if traits_content.0 == traits_content.1 { + msg.extend([ + StringPart::normal("\nbut it "), + StringPart::highlighted("is"), + StringPart::normal(" implemented for `"), + ]); + msg.extend(types.1.0); + msg.push(StringPart::normal("`")); + } else { + msg.push(StringPart::normal("\nbut trait `")); + msg.extend(traits.1.0); + msg.extend([ + StringPart::normal("` "), + StringPart::highlighted("is"), + StringPart::normal(" implemented for `"), + ]); + msg.extend(types.1.0); + msg.push(StringPart::normal("`")); + } + err.highlighted_help(msg); if let [TypeError::Sorts(exp_found)] = &terrs[..] { let exp_found = self.resolve_vars_if_possible(*exp_found); diff --git a/tests/ui/const-generics/associated-type-bound-fail.stderr b/tests/ui/const-generics/associated-type-bound-fail.stderr index 602a8927a8530..e92aad7cec32c 100644 --- a/tests/ui/const-generics/associated-type-bound-fail.stderr +++ b/tests/ui/const-generics/associated-type-bound-fail.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `u16: Bar` is not satisfied LL | type Assoc = u16; | ^^^ the trait `Bar` is not implemented for `u16` | - = help: the trait `Bar<3>` is implemented for `u16` + = help: the trait `Bar` is not implemented for `u16` + but trait `Bar<3>` is implemented for it note: required by a bound in `Foo::Assoc` --> $DIR/associated-type-bound-fail.rs:4:17 | diff --git a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr index 45be3126e3b3f..e36f645b2637b 100644 --- a/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr +++ b/tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr @@ -18,7 +18,8 @@ LL | LL | 1_u32 | ----- return type was inferred to be `u32` here | - = help: the trait `Traitor` is implemented for `u32` + = help: the trait `Traitor` is not implemented for `u32` + but trait `Traitor` is implemented for it error[E0277]: the trait bound `u64: Traitor` is not satisfied --> $DIR/rp_impl_trait_fail.rs:21:13 @@ -29,7 +30,8 @@ LL | LL | 1_u64 | ----- return type was inferred to be `u64` here | - = help: the trait `Traitor<1, 2>` is implemented for `u64` + = help: the trait `Traitor<1, 1>` is not implemented for `u64` + but trait `Traitor<1, 2>` is implemented for it error[E0284]: type annotations needed --> $DIR/rp_impl_trait_fail.rs:28:5 diff --git a/tests/ui/const-generics/defaults/trait_objects_fail.stderr b/tests/ui/const-generics/defaults/trait_objects_fail.stderr index 481d77728b9ef..2390dfeadb906 100644 --- a/tests/ui/const-generics/defaults/trait_objects_fail.stderr +++ b/tests/ui/const-generics/defaults/trait_objects_fail.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied LL | foo(&10_u32); | ^^^^^^^ the trait `Trait` is not implemented for `u32` | - = help: the trait `Trait<2>` is implemented for `u32` + = help: the trait `Trait<12>` is not implemented for `u32` + but trait `Trait<2>` is implemented for it = note: required for the cast from `&u32` to `&dyn Trait` error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied @@ -13,7 +14,8 @@ error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied LL | bar(&true); | ^^^^^ the trait `Traitor<_>` is not implemented for `bool` | - = help: the trait `Traitor<2, 3>` is implemented for `bool` + = help: the trait `Traitor<_, _>` is not implemented for `bool` + but trait `Traitor<2, 3>` is implemented for it = note: required for the cast from `&bool` to `&dyn Traitor<_>` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/defaults/wfness.stderr b/tests/ui/const-generics/defaults/wfness.stderr index bd9bfcd7dadf6..290a80bd32fa0 100644 --- a/tests/ui/const-generics/defaults/wfness.stderr +++ b/tests/ui/const-generics/defaults/wfness.stderr @@ -10,7 +10,8 @@ error[E0277]: the trait bound `(): Trait<2>` is not satisfied LL | (): Trait; | ^^^^^^^^ the trait `Trait<2>` is not implemented for `()` | - = help: the trait `Trait<3>` is implemented for `()` + = help: the trait `Trait<2>` is not implemented for `()` + but trait `Trait<3>` is implemented for it error[E0277]: the trait bound `(): Trait<1>` is not satisfied --> $DIR/wfness.rs:18:13 @@ -18,7 +19,8 @@ error[E0277]: the trait bound `(): Trait<1>` is not satisfied LL | fn foo() -> DependentDefaultWfness { | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<1>` is not implemented for `()` | - = help: the trait `Trait<3>` is implemented for `()` + = help: the trait `Trait<1>` is not implemented for `()` + but trait `Trait<3>` is implemented for it note: required by a bound in `WhereClause` --> $DIR/wfness.rs:8:9 | diff --git a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr index 0184a05932707..07e86aa17f2d2 100644 --- a/tests/ui/const-generics/occurs-check/unused-substs-1.stderr +++ b/tests/ui/const-generics/occurs-check/unused-substs-1.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `A<_>: Bar<_>` is not satisfied LL | let _ = A; | ^ the trait `Bar<_>` is not implemented for `A<_>` | - = help: the trait `Bar<_>` is implemented for `A<{ 6 + 1 }>` + = help: the trait `Bar<_>` is not implemented for `A<_>` + but it is implemented for `A<{ 6 + 1 }>` note: required by a bound in `A` --> $DIR/unused-substs-1.rs:9:11 | diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr index 41f222e46a77c..5d0c182641101 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.current.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `&str: AsExpression` is not satisfied LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` | - = help: the trait `AsExpression` is implemented for `&str` + = help: the trait `AsExpression` is not implemented for `&str` + but trait `AsExpression` is implemented for it = help: for that trait implementation, expected `Text`, found `Integer` error: aborting due to 1 previous error diff --git a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr index 8c01b61191e60..1e1eae852f911 100644 --- a/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr +++ b/tests/ui/diagnostic_namespace/do_not_recommend/as_expression.next.stderr @@ -22,7 +22,8 @@ error[E0277]: the trait bound `&str: AsExpression` is not satisfied LL | SelectInt.check("bar"); | ^^^^^ the trait `AsExpression` is not implemented for `&str` | - = help: the trait `AsExpression` is implemented for `&str` + = help: the trait `AsExpression` is not implemented for `&str` + but trait `AsExpression` is implemented for it = help: for that trait implementation, expected `Text`, found `Integer` error[E0271]: type mismatch resolving `::SqlType == Text` diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr index 14894cef77089..de252b816e58a 100644 --- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr @@ -16,7 +16,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied LL | let () = K::<()>; | ^^ the trait `From<()>` is not implemented for `Infallible` | - = help: the trait `From` is implemented for `Infallible` + = help: the trait `From<()>` is not implemented for `Infallible` + but trait `From` is implemented for it = help: for that trait implementation, expected `!`, found `()` note: required by a bound in `K` --> $DIR/unsatisfied-bounds.rs:12:17 @@ -48,7 +49,8 @@ error[E0277]: the trait bound `Infallible: From<()>` is not satisfied LL | let _ = <() as Trait<&'static str>>::B::<()>; | ^^ the trait `From<()>` is not implemented for `Infallible` | - = help: the trait `From` is implemented for `Infallible` + = help: the trait `From<()>` is not implemented for `Infallible` + but trait `From` is implemented for it = help: for that trait implementation, expected `!`, found `()` note: required by a bound in `Trait::B` --> $DIR/unsatisfied-bounds.rs:21:21 diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg index a18fc11a1e3c6..277fd1536bc71 100644 --- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg +++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg @@ -1,4 +1,4 @@ - + diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index 768224e4c515c..663c9a7f2aeda 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -32,7 +32,8 @@ LL | fn foo>(self) -> impl Foo { LL | self | ---- return type was inferred to be `Bar` here | - = help: the trait `Foo` is implemented for `Bar` + = help: the trait `Foo` is not implemented for `Bar` + but trait `Foo` is implemented for it = help: for that trait implementation, expected `char`, found `u8` error: aborting due to 3 previous errors diff --git a/tests/ui/impl-trait/issues/issue-62742.stderr b/tests/ui/impl-trait/issues/issue-62742.stderr index 94822e41ccd67..98d17b02536cc 100644 --- a/tests/ui/impl-trait/issues/issue-62742.stderr +++ b/tests/ui/impl-trait/issues/issue-62742.stderr @@ -29,7 +29,8 @@ error[E0277]: the trait bound `RawImpl<_>: Raw<_>` is not satisfied LL | WrongImpl::foo(0i32); | ^^^^^^^^^ the trait `Raw<_>` is not implemented for `RawImpl<_>` | - = help: the trait `Raw<[_]>` is implemented for `RawImpl<_>` + = help: the trait `Raw<_>` is not implemented for `RawImpl<_>` + but trait `Raw<[_]>` is implemented for it note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:33:35 | @@ -67,7 +68,8 @@ error[E0277]: the trait bound `RawImpl<()>: Raw<()>` is not satisfied LL | WrongImpl::<()>::foo(0i32); | ^^^^^^^^^^^^^^^ the trait `Raw<()>` is not implemented for `RawImpl<()>` | - = help: the trait `Raw<[()]>` is implemented for `RawImpl<()>` + = help: the trait `Raw<()>` is not implemented for `RawImpl<()>` + but trait `Raw<[()]>` is implemented for it = help: for that trait implementation, expected `[()]`, found `()` note: required by a bound in `SafeImpl` --> $DIR/issue-62742.rs:33:35 diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index d98de650d0d88..2e95ef370c7fd 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -83,7 +83,8 @@ error[E0277]: the trait bound `for<'a> &'a (): Qux<'b>` is not satisfied LL | fn one_hrtb_mention_fn_trait_param_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl Qux<'b>> {} | ^^^^^^^^^^^^ the trait `for<'a> Qux<'b>` is not implemented for `&'a ()` | - = help: the trait `Qux<'_>` is implemented for `()` + = help: the trait `Qux<'b>` is not implemented for `&'a ()` + but trait `Qux<'_>` is implemented for `()` = help: for that trait implementation, expected `()`, found `&'a ()` error: implementation of `Bar` is not general enough @@ -101,7 +102,8 @@ error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied LL | fn two_htrb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Qux<'b>> {} | ^^^^^^^^^^^^^^^^^^^^ the trait `for<'a, 'b> Qux<'b>` is not implemented for `&'a ()` | - = help: the trait `Qux<'_>` is implemented for `()` + = help: the trait `Qux<'b>` is not implemented for `&'a ()` + but trait `Qux<'_>` is implemented for `()` = help: for that trait implementation, expected `()`, found `&'a ()` error: aborting due to 9 previous errors diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index 4ec28ddf87171..d4637da1426a2 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -5,7 +5,8 @@ LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` - = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec<{integer}>` to implement `Index` diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index 3041c2c99a108..fdcf9b030a5e8 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -5,7 +5,8 @@ LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` - = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[{integer}]` to implement `Index` = note: 1 redundant requirement hidden diff --git a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr index 4cced22789f74..0752231356cfc 100644 --- a/tests/ui/indexing/point-at-index-for-obligation-failure.stderr +++ b/tests/ui/indexing/point-at-index-for-obligation-failure.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `String: Borrow<&str>` is not satisfied LL | &s | ^^ the trait `Borrow<&str>` is not implemented for `String` | - = help: the trait `Borrow` is implemented for `String` + = help: the trait `Borrow<&_>` is not implemented for `String` + but trait `Borrow<_>` is implemented for it = help: for that trait implementation, expected `str`, found `&str` = note: required for `HashMap` to implement `Index<&&str>` diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index 97e658617cf03..f731d303774c3 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -5,7 +5,8 @@ LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` - = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `Vec` to implement `Index` @@ -16,7 +17,8 @@ LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` - = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `Vec` to implement `Index` @@ -27,7 +29,8 @@ LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` - = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `Vec` to implement `Index` @@ -38,7 +41,8 @@ LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` - = help: the trait `SliceIndex<[isize]>` is implemented for `usize` + = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `Vec` to implement `Index` @@ -49,7 +53,8 @@ LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` - = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` = note: required for `[u8]` to implement `Index` @@ -60,7 +65,8 @@ LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` - = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` = note: required for `[u8]` to implement `Index` @@ -71,7 +77,8 @@ LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` - = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` = note: required for `[u8]` to implement `Index` @@ -82,7 +89,8 @@ LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` - = help: the trait `SliceIndex<[u8]>` is implemented for `usize` + = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[u8]` to implement `Index` diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index e14629f5f3aa2..8213136faa1dd 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -18,7 +18,8 @@ LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_rece | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` - = help: the trait `FromIterator<(u32, _, _)>` is implemented for `Vec<(u32, _, _)>` + = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` + but trait `FromIterator<(u32, _, _)>` is implemented for it = help: for that trait implementation, expected `(u32, _, _)`, found `()` note: the method call chain might not have had the expected associated types --> $DIR/issue-34334.rs:5:43 diff --git a/tests/ui/issues/issue-45801.stderr b/tests/ui/issues/issue-45801.stderr index 5a10c429564c4..940c1865fa398 100644 --- a/tests/ui/issues/issue-45801.stderr +++ b/tests/ui/issues/issue-45801.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `Params: Plugin` is not satisfied LL | req.get_ref::(); | ^^^^^^^ the trait `Plugin` is not implemented for `Params` | - = help: the trait `Plugin` is implemented for `Params` + = help: the trait `Plugin` is not implemented for `Params` + but trait `Plugin` is implemented for it = help: for that trait implementation, expected `Foo`, found `i32` error: aborting due to 1 previous error diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr index 128288e28f5ac..e62be48edf6bd 100644 --- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -5,7 +5,8 @@ LL | let x2: Vec = x1.into_iter().collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<&_>` is not implemented for `Vec` + but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `f64`, found `&f64` note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:8:27 @@ -26,7 +27,8 @@ LL | let x3 = x1.into_iter().collect::>(); | required by a bound introduced by this call | = help: the trait `FromIterator<&f64>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<&_>` is not implemented for `Vec` + but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `f64`, found `&f64` note: the method call chain might not have had the expected associated types --> $DIR/issue-66923-show-error-for-correct-call.rs:12:17 diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr index 3d3bbab881926..d6f82741c4c34 100644 --- a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr @@ -7,7 +7,8 @@ LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&X>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<&_>` is not implemented for `Vec` + but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `X`, found `&X` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain-fixable.rs:5:26 @@ -124,7 +125,8 @@ LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<()>` is not implemented for `Vec` + but trait `FromIterator` is implemented for it = help: for that trait implementation, expected `i32`, found `()` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain-fixable.rs:32:15 diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index bc35fcd489df5..2522471b3b5e8 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -7,7 +7,8 @@ LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<&X>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<&_>` is not implemented for `Vec` + but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `X`, found `&X` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:4:26 @@ -181,7 +182,8 @@ LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | = help: the trait `FromIterator<()>` is not implemented for `Vec` - = help: the trait `FromIterator` is implemented for `Vec` + = help: the trait `FromIterator<()>` is not implemented for `Vec` + but trait `FromIterator` is implemented for it = help: for that trait implementation, expected `i32`, found `()` note: the method call chain might not have had the expected associated types --> $DIR/invalid-iterator-chain.rs:44:15 diff --git a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr b/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr index 3b8913ccf4577..9eacab9a0b775 100644 --- a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr +++ b/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied LL | >::from(never); // Should the inference fail? | ^ the trait `From<()>` is not implemented for `E` | - = help: the trait `From` is implemented for `E` + = help: the trait `From<()>` is not implemented for `E` + but trait `From` is implemented for it = help: for that trait implementation, expected `!`, found `()` error: aborting due to 1 previous error diff --git a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr index f5249814c785c..d6234c8e7e15e 100644 --- a/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr +++ b/tests/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `E: From<()>` is not satisfied LL | >::from(never); | ^ the trait `From<()>` is not implemented for `E` | - = help: the trait `From` is implemented for `E` + = help: the trait `From<()>` is not implemented for `E` + but trait `From` is implemented for it = help: for that trait implementation, expected `!`, found `()` error: aborting due to 1 previous error diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr index e2ba2474d6c6e..cdb9172ef0f12 100644 --- a/tests/ui/on-unimplemented/impl-substs.stderr +++ b/tests/ui/on-unimplemented/impl-substs.stderr @@ -7,7 +7,8 @@ LL | Foo::::foo((1i32, 1i32, 1i32)); | required by a bound introduced by this call | = help: the trait `Foo` is not implemented for `(i32, i32, i32)` - = help: the trait `Foo` is implemented for `(i32, i32, i32)` + = help: the trait `Foo` is not implemented for `(i32, i32, i32)` + but trait `Foo` is implemented for it = help: for that trait implementation, expected `i32`, found `usize` error: aborting due to 1 previous error diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr index c7d2a78af6cba..d20b559def7c4 100644 --- a/tests/ui/on-unimplemented/on-impl.stderr +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -7,7 +7,8 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | required by a bound introduced by this call | = help: the trait `Index` is not implemented for `[i32]` - = help: the trait `Index` is implemented for `[i32]` + = help: the trait `Index` is not implemented for `[i32]` + but trait `Index` is implemented for it = help: for that trait implementation, expected `usize`, found `u32` error[E0277]: the trait bound `[i32]: Index` is not satisfied @@ -17,7 +18,8 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | = help: the trait `Index` is not implemented for `[i32]` - = help: the trait `Index` is implemented for `[i32]` + = help: the trait `Index` is not implemented for `[i32]` + but trait `Index` is implemented for it = help: for that trait implementation, expected `usize`, found `u32` error: aborting due to 2 previous errors diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index d53ecb9db0cd5..8f7169b30d401 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -5,7 +5,8 @@ LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` - = help: the trait `SliceIndex<[i32]>` is implemented for `usize` + = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` + but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` = note: required for `[i32]` to implement `Index` diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index e8bbb8058faf3..0ce0c20756159 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -7,7 +7,8 @@ LL | let _: u8 = s[4]; = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `{integer}` + but trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index<{integer}>` @@ -22,7 +23,8 @@ LL | let _ = s.get(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `{integer}` + but trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -38,7 +40,8 @@ LL | let _ = s.get_unchecked(4); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `{integer}` + but trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_unchecked` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index 9390d689252f8..7bc46ff33b38a 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -31,7 +31,8 @@ LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | = help: the trait `SliceIndex` is not implemented for `usize` - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `usize` + but trait `SliceIndex<[_]>` is implemented for it = help: for that trait implementation, expected `[_]`, found `str` = note: required for `str` to implement `Index` @@ -46,7 +47,8 @@ LL | s.get_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `{integer}` + but trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL @@ -62,7 +64,8 @@ LL | s.get_unchecked_mut(1); = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: - = help: the trait `SliceIndex<[_]>` is implemented for `usize` + = help: the trait `SliceIndex` is not implemented for `{integer}` + but trait `SliceIndex<[_]>` is implemented for `usize` = help: for that trait implementation, expected `[_]`, found `str` note: required by a bound in `core::str::::get_unchecked_mut` --> $SRC_DIR/core/src/str/mod.rs:LL:COL diff --git a/tests/ui/suggestions/issue-101623.stderr b/tests/ui/suggestions/issue-101623.stderr index 4de91a1b99500..0733e67ea029e 100644 --- a/tests/ui/suggestions/issue-101623.stderr +++ b/tests/ui/suggestions/issue-101623.stderr @@ -7,7 +7,8 @@ LL | Trait::do_stuff({ fun(&mut *inner) }); | | the trait `Trait<'_>` is not implemented for `*mut ()` | required by a bound introduced by this call | - = help: the trait `Trait<'_>` is implemented for `()` + = help: the trait `Trait<'_>` is not implemented for `*mut ()` + but it is implemented for `()` = help: for that trait implementation, expected `()`, found `*mut ()` error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index 2316acbe9da28..cd5364fcffba9 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -5,7 +5,8 @@ LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` - = help: the trait `SliceIndex<[{integer}]>` is implemented for `usize` + = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_` + but it is implemented for `_` = help: for that trait implementation, expected `usize`, found `&usize` = note: required for `[{integer}]` to implement `Index<&usize>` = note: 1 redundant requirement hidden diff --git a/tests/ui/traits/coercion-generic-bad.stderr b/tests/ui/traits/coercion-generic-bad.stderr index 26136c6f72c8b..c0553ea62c504 100644 --- a/tests/ui/traits/coercion-generic-bad.stderr +++ b/tests/ui/traits/coercion-generic-bad.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `Struct: Trait` is not satisfied LL | let s: Box> = Box::new(Struct { person: "Fred" }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `Struct` | - = help: the trait `Trait<&'static str>` is implemented for `Struct` + = help: the trait `Trait` is not implemented for `Struct` + but trait `Trait<&'static str>` is implemented for it = help: for that trait implementation, expected `&'static str`, found `isize` = note: required for the cast from `Box` to `Box>` diff --git a/tests/ui/traits/negative-bounds/simple.stderr b/tests/ui/traits/negative-bounds/simple.stderr index b8d12138794bf..f8a43e605c477 100644 --- a/tests/ui/traits/negative-bounds/simple.stderr +++ b/tests/ui/traits/negative-bounds/simple.stderr @@ -28,7 +28,8 @@ error[E0277]: the trait bound `Copyable: !Copy` is not satisfied LL | not_copy::(); | ^^^^^^^^ the trait bound `Copyable: !Copy` is not satisfied | - = help: the trait `Copy` is implemented for `Copyable` + = help: the trait `Copy` is not implemented for `Copyable` + but trait `Copy` is implemented for it note: required by a bound in `not_copy` --> $DIR/simple.rs:3:16 | diff --git a/tests/ui/try-block/try-block-bad-type.stderr b/tests/ui/try-block/try-block-bad-type.stderr index d94962e403172..c67ad762a83b9 100644 --- a/tests/ui/try-block/try-block-bad-type.stderr +++ b/tests/ui/try-block/try-block-bad-type.stderr @@ -7,7 +7,8 @@ LL | Err("")?; | this can't be annotated with `?` because it has type `Result<_, &str>` | = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait - = help: the trait `From` is implemented for `TryFromSliceError` + = help: the trait `From<&str>` is not implemented for `TryFromSliceError` + but trait `From` is implemented for it = help: for that trait implementation, expected `Infallible`, found `&str` = note: required for `Result` to implement `FromResidual>` diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index fe28912ba0077..20fe2d721bc30 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -67,7 +67,8 @@ LL | ControlFlow::Continue(Err("hello")?) | ^ this `?` produces `Result`, which is incompatible with `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + but trait `FromResidual>` is implemented for it = help: for that trait implementation, expected `ControlFlow`, found `Result` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` @@ -79,7 +80,8 @@ LL | Some(3)?; | ^ this `?` produces `Option`, which is incompatible with `ControlFlow` | = help: the trait `FromResidual>` is not implemented for `ControlFlow` - = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + but trait `FromResidual>` is implemented for it = help: for that trait implementation, expected `ControlFlow`, found `Option` error[E0277]: the `?` operator in a function that returns `ControlFlow` can only be used on other `ControlFlow`s (with the same Break type) @@ -92,7 +94,8 @@ LL | ControlFlow::Break(4_u8)?; | = help: the trait `FromResidual>` is not implemented for `ControlFlow` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` - = help: the trait `FromResidual>` is implemented for `ControlFlow` + = help: the trait `FromResidual>` is not implemented for `ControlFlow` + but trait `FromResidual>` is implemented for it = help: for that trait implementation, expected `i64`, found `u8` error: aborting due to 8 previous errors diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr index c215d197db436..d96c86a2e6f16 100644 --- a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr +++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `Foo: Trait` is not satisfied LL | let x = >::Assoc::default(); | ^^^ the trait `Trait` is not implemented for `Foo` | - = help: the trait `Trait<()>` is implemented for `Foo` + = help: the trait `Trait` is not implemented for `Foo` + but trait `Trait<()>` is implemented for it error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr index 34532afcbbae4..915432bbe675f 100644 --- a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr +++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr @@ -7,7 +7,8 @@ LL | fn foo() -> impl Foo { LL | () | -- return type was inferred to be `()` here | - = help: the trait `Foo<()>` is implemented for `()` + = help: the trait `Foo` is not implemented for `()` + but trait `Foo<()>` is implemented for it error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr index 3ae3590ca7fe3..1e799f156352f 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr @@ -7,7 +7,8 @@ LL | 42_i32 | ------ return type was inferred to be `i32` here | = help: the trait `PartialEq` is not implemented for `i32` - = help: the trait `PartialEq` is implemented for `i32` + = help: the trait `PartialEq` is not implemented for `i32` + but trait `PartialEq` is implemented for it error: aborting due to 1 previous error diff --git a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr index ab307aadec9ff..5c0d98735f7ff 100644 --- a/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr +++ b/tests/ui/typeck/suggest-similar-impls-for-root-obligation.stderr @@ -4,7 +4,8 @@ error[E0277]: the trait bound `((),): Into` is not satisfied LL | let _: Bar = ((),).into(); | ^^^^ the trait `Foo<'_>` is not implemented for `((),)` | - = help: the trait `Foo<'_>` is implemented for `()` + = help: the trait `Foo<'_>` is not implemented for `((),)` + but it is implemented for `()` = help: for that trait implementation, expected `()`, found `((),)` note: required for `Bar` to implement `From<((),)>` --> $DIR/suggest-similar-impls-for-root-obligation.rs:7:22 From e169483879e73141bec00004c3c68eaa9652423b Mon Sep 17 00:00:00 2001 From: ismailarilik Date: Fri, 1 Nov 2024 20:19:01 +0300 Subject: [PATCH 09/16] refactor(config): remove FIXME statement in comment of `omit-git-hash` It is already fixed. --- config.example.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/config.example.toml b/config.example.toml index 9072a83551a7e..cd7ec6a05bc10 100644 --- a/config.example.toml +++ b/config.example.toml @@ -668,8 +668,6 @@ # Flag indicating whether git info will be retrieved from .git automatically. # Having the git information can cause a lot of rebuilds during development. -# -# FIXME(#76720): this can causes bugs if different compilers reuse the same metadata cache. #omit-git-hash = if rust.channel == "dev" { true } else { false } # Whether to create a source tarball by default when running `x dist`. From 26ed32ccdbb583d574a1a04fad038f6211e3c9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 24 Oct 2024 22:38:50 +0000 Subject: [PATCH 10/16] Trim output of E0277 in some cases Remove default note for "trait is not implemented" in favor of the more colorful diff output from the previous commit. Removes duplicated output. --- .../traits/fulfillment_errors.rs | 20 +++++++++++++++++-- tests/ui/indexing/index-help.stderr | 1 - .../indexing/indexing-requires-a-uint.stderr | 1 - tests/ui/integral-indexing.stderr | 8 -------- tests/ui/issues/issue-34334.stderr | 1 - ...e-66923-show-error-for-correct-call.stderr | 2 -- .../invalid-iterator-chain-fixable.stderr | 2 -- .../iterators/invalid-iterator-chain.stderr | 2 -- tests/ui/on-unimplemented/impl-substs.stderr | 1 - tests/ui/on-unimplemented/on-impl.stderr | 2 -- tests/ui/on-unimplemented/slice-index.stderr | 1 - tests/ui/str/str-idx.stderr | 3 --- tests/ui/str/str-mut-idx.stderr | 3 --- .../suggest-dereferencing-index.stderr | 1 - tests/ui/try-trait/bad-interconversion.stderr | 3 --- .../self-referential-2.current.stderr | 1 - 16 files changed, 18 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 358c244eca941..dd2f0ec2096b2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -6,8 +6,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, StringPart, Suggestions, pluralize, - struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, Level, MultiSpan, StashKey, StringPart, Suggestions, + pluralize, struct_span_code_err, }; use rustc_hir::def::Namespace; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -1833,6 +1833,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return false; } + if let [child, ..] = &err.children[..] + && child.level == Level::Help + && let Some(line) = child.messages.get(0) + && let Some(line) = line.0.as_str() + && line.starts_with("the trait") + && line.contains("is not implemented for") + { + // HACK(estebank): we remove the pre-existing + // "the trait `X` is not implemented for" note, which only happens if there + // was a custom label. We do this because we want that note to always be the + // first, and making this logic run earlier will get tricky. For now, we + // instead keep the logic the same and modify the already constructed error + // to avoid the wording duplication. + err.children.remove(0); + } + let traits = self.cmp_traits( obligation_trait_ref.def_id, &obligation_trait_ref.args[1..], diff --git a/tests/ui/indexing/index-help.stderr b/tests/ui/indexing/index-help.stderr index d4637da1426a2..1974e13eabcee 100644 --- a/tests/ui/indexing/index-help.stderr +++ b/tests/ui/indexing/index-help.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `i32` LL | x[0i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` diff --git a/tests/ui/indexing/indexing-requires-a-uint.stderr b/tests/ui/indexing/indexing-requires-a-uint.stderr index fdcf9b030a5e8..5c60a30946d37 100644 --- a/tests/ui/indexing/indexing-requires-a-uint.stderr +++ b/tests/ui/indexing/indexing-requires-a-uint.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `u8` LL | [0][0u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` diff --git a/tests/ui/integral-indexing.stderr b/tests/ui/integral-indexing.stderr index f731d303774c3..e7a45c2c88dd9 100644 --- a/tests/ui/integral-indexing.stderr +++ b/tests/ui/integral-indexing.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `[isize]` cannot be indexed by `u8` LL | v[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` = help: the trait `SliceIndex<[isize]>` is not implemented for `u8` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` @@ -16,7 +15,6 @@ error[E0277]: the type `[isize]` cannot be indexed by `i8` LL | v[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` = help: the trait `SliceIndex<[isize]>` is not implemented for `i8` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` @@ -28,7 +26,6 @@ error[E0277]: the type `[isize]` cannot be indexed by `u32` LL | v[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` = help: the trait `SliceIndex<[isize]>` is not implemented for `u32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` @@ -40,7 +37,6 @@ error[E0277]: the type `[isize]` cannot be indexed by `i32` LL | v[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` = help: the trait `SliceIndex<[isize]>` is not implemented for `i32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` @@ -52,7 +48,6 @@ error[E0277]: the type `[u8]` cannot be indexed by `u8` LL | s.as_bytes()[3u8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` = help: the trait `SliceIndex<[u8]>` is not implemented for `u8` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u8` @@ -64,7 +59,6 @@ error[E0277]: the type `[u8]` cannot be indexed by `i8` LL | s.as_bytes()[3i8]; | ^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` = help: the trait `SliceIndex<[u8]>` is not implemented for `i8` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i8` @@ -76,7 +70,6 @@ error[E0277]: the type `[u8]` cannot be indexed by `u32` LL | s.as_bytes()[3u32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` = help: the trait `SliceIndex<[u8]>` is not implemented for `u32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `u32` @@ -88,7 +81,6 @@ error[E0277]: the type `[u8]` cannot be indexed by `i32` LL | s.as_bytes()[3i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` = help: the trait `SliceIndex<[u8]>` is not implemented for `i32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` diff --git a/tests/ui/issues/issue-34334.stderr b/tests/ui/issues/issue-34334.stderr index 8213136faa1dd..6562ccfdcd286 100644 --- a/tests/ui/issues/issue-34334.stderr +++ b/tests/ui/issues/issue-34334.stderr @@ -17,7 +17,6 @@ error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterato LL | let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect(); | ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>` but trait `FromIterator<(u32, _, _)>` is implemented for it = help: for that trait implementation, expected `(u32, _, _)`, found `()` diff --git a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr index e62be48edf6bd..d2852093725ce 100644 --- a/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr +++ b/tests/ui/issues/issue-66923-show-error-for-correct-call.stderr @@ -4,7 +4,6 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over e LL | let x2: Vec = x1.into_iter().collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator<&_>` is not implemented for `Vec` but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `f64`, found `&f64` @@ -26,7 +25,6 @@ LL | let x3 = x1.into_iter().collect::>(); | | | required by a bound introduced by this call | - = help: the trait `FromIterator<&f64>` is not implemented for `Vec` = help: the trait `FromIterator<&_>` is not implemented for `Vec` but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `f64`, found `&f64` diff --git a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr index d6f82741c4c34..09439fe8fbd66 100644 --- a/tests/ui/iterators/invalid-iterator-chain-fixable.stderr +++ b/tests/ui/iterators/invalid-iterator-chain-fixable.stderr @@ -6,7 +6,6 @@ LL | let i = i.map(|x| x.clone()); LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<&X>` is not implemented for `Vec` = help: the trait `FromIterator<&_>` is not implemented for `Vec` but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `X`, found `&X` @@ -124,7 +123,6 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over e LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<()>` is not implemented for `Vec` = help: the trait `FromIterator<()>` is not implemented for `Vec` but trait `FromIterator` is implemented for it = help: for that trait implementation, expected `i32`, found `()` diff --git a/tests/ui/iterators/invalid-iterator-chain.stderr b/tests/ui/iterators/invalid-iterator-chain.stderr index 2522471b3b5e8..b810e06d0f7e4 100644 --- a/tests/ui/iterators/invalid-iterator-chain.stderr +++ b/tests/ui/iterators/invalid-iterator-chain.stderr @@ -6,7 +6,6 @@ LL | let i = i.map(|x| x.clone()); LL | i.collect() | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<&X>` is not implemented for `Vec` = help: the trait `FromIterator<&_>` is not implemented for `Vec` but trait `FromIterator<_>` is implemented for it = help: for that trait implementation, expected `X`, found `&X` @@ -181,7 +180,6 @@ error[E0277]: a value of type `Vec` cannot be built from an iterator over e LL | let g: Vec = f.collect(); | ^^^^^^^ value of type `Vec` cannot be built from `std::iter::Iterator` | - = help: the trait `FromIterator<()>` is not implemented for `Vec` = help: the trait `FromIterator<()>` is not implemented for `Vec` but trait `FromIterator` is implemented for it = help: for that trait implementation, expected `i32`, found `()` diff --git a/tests/ui/on-unimplemented/impl-substs.stderr b/tests/ui/on-unimplemented/impl-substs.stderr index cdb9172ef0f12..b85d45eba5bbc 100644 --- a/tests/ui/on-unimplemented/impl-substs.stderr +++ b/tests/ui/on-unimplemented/impl-substs.stderr @@ -6,7 +6,6 @@ LL | Foo::::foo((1i32, 1i32, 1i32)); | | | required by a bound introduced by this call | - = help: the trait `Foo` is not implemented for `(i32, i32, i32)` = help: the trait `Foo` is not implemented for `(i32, i32, i32)` but trait `Foo` is implemented for it = help: for that trait implementation, expected `i32`, found `usize` diff --git a/tests/ui/on-unimplemented/on-impl.stderr b/tests/ui/on-unimplemented/on-impl.stderr index d20b559def7c4..5e7e2c4ea7744 100644 --- a/tests/ui/on-unimplemented/on-impl.stderr +++ b/tests/ui/on-unimplemented/on-impl.stderr @@ -6,7 +6,6 @@ LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | | | required by a bound introduced by this call | - = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is not implemented for `[i32]` but trait `Index` is implemented for it = help: for that trait implementation, expected `usize`, found `u32` @@ -17,7 +16,6 @@ error[E0277]: the trait bound `[i32]: Index` is not satisfied LL | Index::::index(&[1, 2, 3] as &[i32], 2u32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice | - = help: the trait `Index` is not implemented for `[i32]` = help: the trait `Index` is not implemented for `[i32]` but trait `Index` is implemented for it = help: for that trait implementation, expected `usize`, found `u32` diff --git a/tests/ui/on-unimplemented/slice-index.stderr b/tests/ui/on-unimplemented/slice-index.stderr index 8f7169b30d401..0a9ebe3f088e0 100644 --- a/tests/ui/on-unimplemented/slice-index.stderr +++ b/tests/ui/on-unimplemented/slice-index.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `[i32]` cannot be indexed by `i32` LL | x[1i32]; | ^^^^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` = help: the trait `SliceIndex<[i32]>` is not implemented for `i32` but it is implemented for `usize` = help: for that trait implementation, expected `usize`, found `i32` diff --git a/tests/ui/str/str-idx.stderr b/tests/ui/str/str-idx.stderr index 0ce0c20756159..bedbbd9cb5029 100644 --- a/tests/ui/str/str-idx.stderr +++ b/tests/ui/str/str-idx.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `str` cannot be indexed by `{integer}` LL | let _: u8 = s[4]; | ^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex` is not implemented for `{integer}` @@ -20,7 +19,6 @@ LL | let _ = s.get(4); | | | required by a bound introduced by this call | - = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex` is not implemented for `{integer}` @@ -37,7 +35,6 @@ LL | let _ = s.get_unchecked(4); | | | required by a bound introduced by this call | - = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex` is not implemented for `{integer}` diff --git a/tests/ui/str/str-mut-idx.stderr b/tests/ui/str/str-mut-idx.stderr index 7bc46ff33b38a..f09a4c329e5d8 100644 --- a/tests/ui/str/str-mut-idx.stderr +++ b/tests/ui/str/str-mut-idx.stderr @@ -30,7 +30,6 @@ error[E0277]: the type `str` cannot be indexed by `usize` LL | s[1usize] = bot(); | ^^^^^^ string indices are ranges of `usize` | - = help: the trait `SliceIndex` is not implemented for `usize` = help: the trait `SliceIndex` is not implemented for `usize` but trait `SliceIndex<[_]>` is implemented for it = help: for that trait implementation, expected `[_]`, found `str` @@ -44,7 +43,6 @@ LL | s.get_mut(1); | | | required by a bound introduced by this call | - = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex` is not implemented for `{integer}` @@ -61,7 +59,6 @@ LL | s.get_unchecked_mut(1); | | | required by a bound introduced by this call | - = help: the trait `SliceIndex` is not implemented for `{integer}` = note: you can use `.chars().nth()` or `.bytes().nth()` for more information, see chapter 8 in The Book: = help: the trait `SliceIndex` is not implemented for `{integer}` diff --git a/tests/ui/suggestions/suggest-dereferencing-index.stderr b/tests/ui/suggestions/suggest-dereferencing-index.stderr index cd5364fcffba9..0335d8eafde4b 100644 --- a/tests/ui/suggestions/suggest-dereferencing-index.stderr +++ b/tests/ui/suggestions/suggest-dereferencing-index.stderr @@ -4,7 +4,6 @@ error[E0277]: the type `[{integer}]` cannot be indexed by `&usize` LL | let one_item_please: i32 = [1, 2, 3][i]; | ^ slice indices are of type `usize` or ranges of `usize` | - = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize` = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&_` but it is implemented for `_` = help: for that trait implementation, expected `usize`, found `&usize` diff --git a/tests/ui/try-trait/bad-interconversion.stderr b/tests/ui/try-trait/bad-interconversion.stderr index 20fe2d721bc30..bb5e5646ad294 100644 --- a/tests/ui/try-trait/bad-interconversion.stderr +++ b/tests/ui/try-trait/bad-interconversion.stderr @@ -66,7 +66,6 @@ LL | fn result_to_control_flow() -> ControlFlow { LL | ControlFlow::Continue(Err("hello")?) | ^ this `?` produces `Result`, which is incompatible with `ControlFlow` | - = help: the trait `FromResidual>` is not implemented for `ControlFlow` = help: the trait `FromResidual>` is not implemented for `ControlFlow` but trait `FromResidual>` is implemented for it = help: for that trait implementation, expected `ControlFlow`, found `Result` @@ -79,7 +78,6 @@ LL | fn option_to_control_flow() -> ControlFlow { LL | Some(3)?; | ^ this `?` produces `Option`, which is incompatible with `ControlFlow` | - = help: the trait `FromResidual>` is not implemented for `ControlFlow` = help: the trait `FromResidual>` is not implemented for `ControlFlow` but trait `FromResidual>` is implemented for it = help: for that trait implementation, expected `ControlFlow`, found `Option` @@ -92,7 +90,6 @@ LL | fn control_flow_to_control_flow() -> ControlFlow { LL | ControlFlow::Break(4_u8)?; | ^ this `?` produces `ControlFlow`, which is incompatible with `ControlFlow` | - = help: the trait `FromResidual>` is not implemented for `ControlFlow` = note: unlike `Result`, there's no `From`-conversion performed for `ControlFlow` = help: the trait `FromResidual>` is not implemented for `ControlFlow` but trait `FromResidual>` is implemented for it diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr index 1e799f156352f..e4399f2d8f4d3 100644 --- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr +++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr @@ -6,7 +6,6 @@ LL | fn bar() -> Bar { LL | 42_i32 | ------ return type was inferred to be `i32` here | - = help: the trait `PartialEq` is not implemented for `i32` = help: the trait `PartialEq` is not implemented for `i32` but trait `PartialEq` is implemented for it From 9e108ec1a82dbf5f2990922f1434cb286223443a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Oct 2024 02:41:39 +0000 Subject: [PATCH 11/16] Fix type shortening writing to file Make sure that we append to the file for long ty paths. Do not write the same type more than once. Shorten the calculated width a bit. --- compiler/rustc_middle/src/ty/error.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index c49824bb418cd..43d243b0584e4 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +use std::fs::File; use std::hash::{DefaultHasher, Hash, Hasher}; +use std::io::{Read, Write}; use std::path::PathBuf; use rustc_errors::pluralize; @@ -250,8 +252,8 @@ impl<'tcx> TyCtxt<'tcx> { } let width = self.sess.diagnostic_width(); - let length_limit = width.saturating_sub(30); - if regular.len() <= width { + let length_limit = width / 2; + if regular.len() <= width * 2 / 3 { return regular; } let short = self.ty_string_with_limit(ty, length_limit); @@ -265,7 +267,20 @@ impl<'tcx> TyCtxt<'tcx> { *path = Some(path.take().unwrap_or_else(|| { self.output_filenames(()).temp_path_ext(&format!("long-type-{hash}.txt"), None) })); - match std::fs::write(path.as_ref().unwrap(), &format!("{regular}\n")) { + let Ok(mut file) = + File::options().create(true).read(true).append(true).open(&path.as_ref().unwrap()) + else { + return regular; + }; + + // Do not write the same type to the file multiple times. + let mut contents = String::new(); + let _ = file.read_to_string(&mut contents); + if let Some(_) = contents.lines().find(|line| line == ®ular) { + return short; + } + + match write!(file, "{regular}\n") { Ok(_) => short, Err(_) => regular, } From bf20e236c89f8fe5fd41055292ae2e997869e1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Oct 2024 02:41:55 +0000 Subject: [PATCH 12/16] Use `short_ty_string` --- .../src/error_reporting/traits/fulfillment_errors.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index dd2f0ec2096b2..cc56c67903105 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1872,7 +1872,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { StringPart::normal(" implemented for `"), ]); if types_content.0 == types_content.1 { - msg.push(StringPart::normal(obligation_trait_ref.self_ty().to_string())); + let ty = + self.tcx.short_ty_string(obligation_trait_ref.self_ty(), &mut None); + msg.push(StringPart::normal(ty)); } else { msg.extend(types.0.0); } From 7b73178637907dfb40e25d7c0ba8aa8810d4d889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Oct 2024 04:38:48 +0000 Subject: [PATCH 13/16] Point at tail expression on rpit E0277 ``` error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}: Coroutine` is not satisfied --> $DIR/gen_block_is_coro.rs:6:13 | LL | fn foo() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}` LL | gen { yield 42 } | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}` here ``` The secondary span label is new. --- .../src/error_reporting/traits/suggestions.rs | 39 +++++++++++++------ tests/ui/async-await/async-error-span.stderr | 3 ++ .../arg-count-mismatch-on-unit-input.stderr | 5 ++- tests/ui/coroutine/gen_block_is_coro.stderr | 6 +++ .../coroutine/gen_block_is_no_future.stderr | 2 + tests/ui/coroutine/issue-88653.rs | 1 + tests/ui/coroutine/issue-88653.stderr | 18 +++++++-- ...between-expected-trait-and-found-trait.svg | 30 +++++++------- tests/ui/impl-trait/issue-55872-1.stderr | 6 +++ tests/ui/impl-trait/issue-55872-3.stderr | 3 ++ tests/ui/impl-trait/nested_impl_trait.stderr | 8 +++- .../opaque-cast-field-access-in-future.stderr | 3 ++ ...ction-mismatch-in-impl-where-clause.stderr | 3 ++ .../lifetime-elision-return-type-trait.stderr | 3 ++ tests/ui/lint/issue-106991.stderr | 3 ++ .../ui/never_type/impl_trait_fallback2.stderr | 6 +++ .../ui/never_type/impl_trait_fallback3.stderr | 3 ++ .../ui/never_type/impl_trait_fallback4.stderr | 3 ++ .../ui/type-alias-impl-trait/fallback.stderr | 5 ++- .../non-lifetime-binder-in-constraint.stderr | 3 ++ 20 files changed, 121 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 553bb61ed043b..64edeb35dd257 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3563,17 +3563,34 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { )]); } ObligationCauseCode::OpaqueReturnType(expr_info) => { - if let Some((expr_ty, hir_id)) = expr_info { - let expr_ty = self.tcx.short_ty_string(expr_ty, long_ty_file); - let expr = self.infcx.tcx.hir().expect_expr(hir_id); - err.span_label( - expr.span, - with_forced_trimmed_paths!(format!( - "return type was inferred to be `{expr_ty}` here", - )), - ); - suggest_remove_deref(err, &expr); - } + let (expr_ty, expr) = if let Some((expr_ty, hir_id)) = expr_info { + let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file); + let expr = tcx.hir().expect_expr(hir_id); + (expr_ty, expr) + } else if let Some(body_id) = tcx.hir_node_by_def_id(body_id).body_id() + && let body = tcx.hir().body(body_id) + && let hir::ExprKind::Block(block, _) = body.value.kind + && let Some(expr) = block.expr + && let Some(expr_ty) = self + .typeck_results + .as_ref() + .and_then(|typeck| typeck.node_type_opt(expr.hir_id)) + && let Some(pred) = predicate.as_clause() + && let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() + && self.can_eq(param_env, pred.self_ty(), expr_ty) + { + let expr_ty = tcx.short_ty_string(expr_ty, long_ty_file); + (expr_ty, expr) + } else { + return; + }; + err.span_label( + expr.span, + with_forced_trimmed_paths!(format!( + "return type was inferred to be `{expr_ty}` here", + )), + ); + suggest_remove_deref(err, &expr); } } } diff --git a/tests/ui/async-await/async-error-span.stderr b/tests/ui/async-await/async-error-span.stderr index 44f1583f4cc33..37b5c329a7d07 100644 --- a/tests/ui/async-await/async-error-span.stderr +++ b/tests/ui/async-await/async-error-span.stderr @@ -3,6 +3,9 @@ error[E0277]: `()` is not a future | LL | fn get_future() -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future +LL | +LL | panic!() + | -------- return type was inferred to be `_` here | = help: the trait `Future` is not implemented for `()` diff --git a/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr index c7d6507fd7940..839299f1c94c2 100644 --- a/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr +++ b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr @@ -5,7 +5,10 @@ LL | fn foo() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^ expected due to this ... LL | |_: ()| {} - | ------- found signature defined here + | ---------- + | | + | found signature defined here + | return type was inferred to be `{coroutine@$DIR/arg-count-mismatch-on-unit-input.rs:8:5: 8:12}` here | = note: expected coroutine signature `fn(u8) -> _` found coroutine signature `fn(()) -> _` diff --git a/tests/ui/coroutine/gen_block_is_coro.stderr b/tests/ui/coroutine/gen_block_is_coro.stderr index afcdce1d58dfc..083e738f3ece7 100644 --- a/tests/ui/coroutine/gen_block_is_coro.stderr +++ b/tests/ui/coroutine/gen_block_is_coro.stderr @@ -3,18 +3,24 @@ error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}: C | LL | fn foo() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}` +LL | gen { yield 42 } + | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:7:5: 7:8}` here error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}: Coroutine` is not satisfied --> $DIR/gen_block_is_coro.rs:10:13 | LL | fn bar() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}` +LL | gen { yield 42 } + | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:11:5: 11:8}` here error[E0277]: the trait bound `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}: Coroutine` is not satisfied --> $DIR/gen_block_is_coro.rs:14:13 | LL | fn baz() -> impl Coroutine { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine` is not implemented for `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}` +LL | gen { yield 42 } + | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_coro.rs:15:5: 15:8}` here error: aborting due to 3 previous errors diff --git a/tests/ui/coroutine/gen_block_is_no_future.stderr b/tests/ui/coroutine/gen_block_is_no_future.stderr index bf0985a76a28e..43e18dbc2a9c1 100644 --- a/tests/ui/coroutine/gen_block_is_no_future.stderr +++ b/tests/ui/coroutine/gen_block_is_no_future.stderr @@ -3,6 +3,8 @@ error[E0277]: `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a fut | LL | fn foo() -> impl std::future::Future { | ^^^^^^^^^^^^^^^^^^^^^^^^ `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` is not a future +LL | gen { yield 42 } + | ---------------- return type was inferred to be `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` here | = help: the trait `Future` is not implemented for `{gen block@$DIR/gen_block_is_no_future.rs:5:5: 5:8}` diff --git a/tests/ui/coroutine/issue-88653.rs b/tests/ui/coroutine/issue-88653.rs index 3afd12a209379..b5936c7960de4 100644 --- a/tests/ui/coroutine/issue-88653.rs +++ b/tests/ui/coroutine/issue-88653.rs @@ -14,6 +14,7 @@ fn foo(bar: bool) -> impl Coroutine<(bool,)> { #[coroutine] |bar| { //~^ NOTE: found signature defined here + //~| NOTE: return type was inferred to be if bar { yield bar; } diff --git a/tests/ui/coroutine/issue-88653.stderr b/tests/ui/coroutine/issue-88653.stderr index 8a23ad17b8b37..ef0cc11dde8e8 100644 --- a/tests/ui/coroutine/issue-88653.stderr +++ b/tests/ui/coroutine/issue-88653.stderr @@ -1,11 +1,21 @@ error[E0631]: type mismatch in coroutine arguments --> $DIR/issue-88653.rs:8:22 | -LL | fn foo(bar: bool) -> impl Coroutine<(bool,)> { - | ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this +LL | fn foo(bar: bool) -> impl Coroutine<(bool,)> { + | ^^^^^^^^^^^^^^^^^^^^^^^ expected due to this ... -LL | |bar| { - | ----- found signature defined here +LL | |bar| { + | ----- + | | + | _____found signature defined here + | | +LL | | +LL | | +LL | | if bar { +LL | | yield bar; +LL | | } +LL | | } + | |_____- return type was inferred to be `{coroutine@$DIR/issue-88653.rs:15:5: 15:10}` here | = note: expected coroutine signature `fn((bool,)) -> _` found coroutine signature `fn(bool) -> _` diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg index 277fd1536bc71..1a79a9d7efa25 100644 --- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg +++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg @@ -1,4 +1,4 @@ - + diff --git a/tests/ui/impl-trait/issue-55872-1.stderr b/tests/ui/impl-trait/issue-55872-1.stderr index 8912cce1b4b5b..2ccca0b562c06 100644 --- a/tests/ui/impl-trait/issue-55872-1.stderr +++ b/tests/ui/impl-trait/issue-55872-1.stderr @@ -12,6 +12,9 @@ error[E0277]: the trait bound `S: Copy` is not satisfied in `(S, T)` | LL | fn foo() -> Self::E { | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `S` +... +LL | (S::default(), T::default()) + | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound @@ -24,6 +27,9 @@ error[E0277]: the trait bound `T: Copy` is not satisfied in `(S, T)` | LL | fn foo() -> Self::E { | ^^^^^^^ within `(S, T)`, the trait `Copy` is not implemented for `T` +... +LL | (S::default(), T::default()) + | ---------------------------- return type was inferred to be `(S, T)` here | = note: required because it appears within the type `(S, T)` help: consider further restricting this bound diff --git a/tests/ui/impl-trait/issue-55872-3.stderr b/tests/ui/impl-trait/issue-55872-3.stderr index f892da2a5353b..98e9fbf415341 100644 --- a/tests/ui/impl-trait/issue-55872-3.stderr +++ b/tests/ui/impl-trait/issue-55872-3.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}: | LL | fn foo() -> Self::E { | ^^^^^^^ the trait `Copy` is not implemented for `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}` +LL | +LL | async {} + | -------- return type was inferred to be `{async block@$DIR/issue-55872-3.rs:15:9: 15:14}` here error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr index 31c3e0c901365..d01c5961e819e 100644 --- a/tests/ui/impl-trait/nested_impl_trait.stderr +++ b/tests/ui/impl-trait/nested_impl_trait.stderr @@ -46,7 +46,9 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:6:46 | LL | fn bad_in_ret_position(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ - return type was inferred to be `impl Into` here + | | + | the trait `From>` is not implemented for `impl Debug` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` @@ -55,7 +57,9 @@ error[E0277]: the trait bound `impl Debug: From>` is not satisfie --> $DIR/nested_impl_trait.rs:19:34 | LL | fn bad(x: impl Into) -> impl Into { x } - | ^^^^^^^^^^^^^^^^^^^^^ the trait `From>` is not implemented for `impl Debug` + | ^^^^^^^^^^^^^^^^^^^^^ - return type was inferred to be `impl Into` here + | | + | the trait `From>` is not implemented for `impl Debug` | = help: the trait `Into` is implemented for `T` = note: required for `impl Into` to implement `Into` diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr index 5ade6a69d4b0d..6866f3f5350b3 100644 --- a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr @@ -3,6 +3,9 @@ error[E0283]: type annotations needed | LL | fn run() -> Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type +LL | +LL | loop {} + | ------- return type was inferred to be `!` here | = note: cannot satisfy `_: Future` diff --git a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr index fa71adc63809f..96e18f1f1cb74 100644 --- a/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr +++ b/tests/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr @@ -3,6 +3,9 @@ error[E0271]: type mismatch resolving `<() as Super>::Assoc == ()` | LL | fn test() -> impl Test { | ^^^^^^^^^ type mismatch resolving `<() as Super>::Assoc == ()` +LL | +LL | () + | -- return type was inferred to be `()` here | note: expected this to be `()` --> $DIR/projection-mismatch-in-impl-where-clause.rs:6:18 diff --git a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr index 1664466df3cb3..f26d6b8d0be13 100644 --- a/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr +++ b/tests/ui/lifetimes/lifetime-elision-return-type-trait.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `Result<(), _>: Future` is not satisfied | LL | fn foo() -> impl Future> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `Result<(), _>` +LL | +LL | Ok(()) + | ------ return type was inferred to be `Result<(), _>` here | help: this trait has no implementations, consider adding one --> $DIR/lifetime-elision-return-type-trait.rs:1:1 diff --git a/tests/ui/lint/issue-106991.stderr b/tests/ui/lint/issue-106991.stderr index 9b4fab68102e2..0441a6377d088 100644 --- a/tests/ui/lint/issue-106991.stderr +++ b/tests/ui/lint/issue-106991.stderr @@ -3,6 +3,9 @@ error[E0271]: expected `foo` to be a fn item that returns `i32`, but it returns | LL | fn bar() -> impl Iterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `()` +... +LL | x.iter_mut().map(foo) + | --------------------- return type was inferred to be `Map>, for<'a> fn(&'a mut Vec) {foo}>` here | = note: required for `Map>, for<'a> fn(&'a mut Vec) {foo}>` to implement `Iterator` diff --git a/tests/ui/never_type/impl_trait_fallback2.stderr b/tests/ui/never_type/impl_trait_fallback2.stderr index 78cc83bdbfadb..4c32dce465b85 100644 --- a/tests/ui/never_type/impl_trait_fallback2.stderr +++ b/tests/ui/never_type/impl_trait_fallback2.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn should_ret_unit() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` +LL | +LL | panic!() + | -------- return type was inferred to be `_` here | = help: the trait `T` is implemented for `i32` @@ -11,6 +14,9 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn a() -> Foo { | ^^^ the trait `T` is not implemented for `()` +LL | +LL | panic!() + | -------- return type was inferred to be `_` here | = help: the trait `T` is implemented for `i32` diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr index e2246eea17c61..fde8d0896dda2 100644 --- a/tests/ui/never_type/impl_trait_fallback3.stderr +++ b/tests/ui/never_type/impl_trait_fallback3.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn a() -> Foo { | ^^^ the trait `T` is not implemented for `()` +... +LL | panic!() + | -------- return type was inferred to be `_` here | help: this trait has no implementations, consider adding one --> $DIR/impl_trait_fallback3.rs:5:1 diff --git a/tests/ui/never_type/impl_trait_fallback4.stderr b/tests/ui/never_type/impl_trait_fallback4.stderr index 8f6b5cfea68a9..c4fc949373ae4 100644 --- a/tests/ui/never_type/impl_trait_fallback4.stderr +++ b/tests/ui/never_type/impl_trait_fallback4.stderr @@ -3,6 +3,9 @@ error[E0277]: the trait bound `(): T` is not satisfied | LL | fn foo() -> impl T { | ^^^^^^ the trait `T` is not implemented for `()` +LL | +LL | panic!() + | -------- return type was inferred to be `_` here | help: this trait has no implementations, consider adding one --> $DIR/impl_trait_fallback4.rs:3:1 diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr index 5250252a0da44..c909ab66f0ee2 100644 --- a/tests/ui/type-alias-impl-trait/fallback.stderr +++ b/tests/ui/type-alias-impl-trait/fallback.stderr @@ -4,7 +4,10 @@ error[E0283]: type annotations needed LL | fn unconstrained_foo() -> Wrapper { | ------------ type must be known at this point LL | Wrapper::Second - | ^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the enum `Wrapper` + | ^^^^^^^^^^^^^^^ + | | + | cannot infer type of the type parameter `T` declared on the enum `Wrapper` + | return type was inferred to be `Wrapper<_>` here | = note: cannot satisfy `_: Copy` help: consider specifying the generic argument diff --git a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr index fa3306ff11fa0..6e5bd34ce3817 100644 --- a/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr +++ b/tests/ui/type-alias-impl-trait/non-lifetime-binder-in-constraint.stderr @@ -17,6 +17,9 @@ error[E0277]: the trait bound `{integer}: Trait<()>` is not satisfied | LL | fn produce() -> impl for Trait<(), Assoc = impl Trait> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<()>` is not implemented for `{integer}` +... +LL | 16 + | -- return type was inferred to be `{integer}` here | help: this trait has no implementations, consider adding one --> $DIR/non-lifetime-binder-in-constraint.rs:4:1 From a019c39723a187ac8269ab890b4171fabfad02be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Oct 2024 05:11:42 +0000 Subject: [PATCH 14/16] On long E0277 primary span label, move it to a `help` Long span labels don't read well. --- .../traits/fulfillment_errors.rs | 5 ++ .../async-closures/not-clone-closure.stderr | 3 +- tests/ui/async-await/coroutine-not-future.rs | 1 + .../async-await/coroutine-not-future.stderr | 30 ++++---- .../const_param_ty_bad.stderr | 3 +- tests/ui/coroutine/clone-impl.rs | 1 + tests/ui/coroutine/clone-impl.stderr | 72 +++++++++---------- tests/ui/coroutine/issue-105084.rs | 1 + tests/ui/coroutine/issue-105084.stderr | 18 ++--- ...rg-where-it-should-have-been-called.stderr | 3 +- tests/ui/suggestions/issue-84973-blacklist.rs | 1 + .../suggestions/issue-84973-blacklist.stderr | 24 +++---- .../bare-fn-no-impl-fn-ptr-99875.stderr | 3 +- tests/ui/transmutability/assoc-bound.stderr | 3 +- .../higher-ranked-fn-type.verbose.stderr | 3 +- 15 files changed, 93 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index cc56c67903105..cef704d832810 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -328,6 +328,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } else if let Some(custom_explanation) = safe_transmute_explanation { err.span_label(span, custom_explanation); + } else if explanation.len() > self.tcx.sess.diagnostic_width() { + // Really long types don't look good as span labels, instead move it + // to a `help`. + err.span_label(span, "unsatisfied trait bound"); + err.help(explanation); } else { err.span_label(span, explanation); } diff --git a/tests/ui/async-await/async-closures/not-clone-closure.stderr b/tests/ui/async-await/async-closures/not-clone-closure.stderr index 8d5612687db28..c2f963f9b924d 100644 --- a/tests/ui/async-await/async-closures/not-clone-closure.stderr +++ b/tests/ui/async-await/async-closures/not-clone-closure.stderr @@ -2,8 +2,9 @@ error[E0277]: the trait bound `NotClonableUpvar: Clone` is not satisfied in `{as --> $DIR/not-clone-closure.rs:32:15 | LL | not_clone.clone(); - | ^^^^^ within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar` + | ^^^^^ unsatisfied trait bound | + = help: within `{async closure@$DIR/not-clone-closure.rs:29:21: 29:34}`, the trait `Clone` is not implemented for `NotClonableUpvar` note: required because it's used within this closure --> $DIR/not-clone-closure.rs:29:21 | diff --git a/tests/ui/async-await/coroutine-not-future.rs b/tests/ui/async-await/coroutine-not-future.rs index 4522743550785..de627333fe44c 100644 --- a/tests/ui/async-await/coroutine-not-future.rs +++ b/tests/ui/async-await/coroutine-not-future.rs @@ -1,4 +1,5 @@ //@ edition:2018 +//@compile-flags: --diagnostic-width=300 #![feature(coroutines, coroutine_trait, stmt_expr_attributes)] use std::future::Future; diff --git a/tests/ui/async-await/coroutine-not-future.stderr b/tests/ui/async-await/coroutine-not-future.stderr index 72921a72a9569..b0f371f6706d1 100644 --- a/tests/ui/async-await/coroutine-not-future.stderr +++ b/tests/ui/async-await/coroutine-not-future.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `impl Future: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:35:21 + --> $DIR/coroutine-not-future.rs:36:21 | LL | takes_coroutine(async_fn()); | --------------- ^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` @@ -7,13 +7,13 @@ LL | takes_coroutine(async_fn()); | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:19:39 + --> $DIR/coroutine-not-future.rs:20:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` error[E0277]: the trait bound `impl Future: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:37:21 + --> $DIR/coroutine-not-future.rs:38:21 | LL | takes_coroutine(returns_async_block()); | --------------- ^^^^^^^^^^^^^^^^^^^^^ the trait `Coroutine<_>` is not implemented for `impl Future` @@ -21,27 +21,27 @@ LL | takes_coroutine(returns_async_block()); | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:19:39 + --> $DIR/coroutine-not-future.rs:20:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` -error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}: Coroutine<_>` is not satisfied - --> $DIR/coroutine-not-future.rs:39:21 +error[E0277]: the trait bound `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}: Coroutine<_>` is not satisfied + --> $DIR/coroutine-not-future.rs:40:21 | LL | takes_coroutine(async {}); - | --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:39:21: 39:26}` + | --------------- ^^^^^^^^ the trait `Coroutine<_>` is not implemented for `{async block@$DIR/coroutine-not-future.rs:40:21: 40:26}` | | | required by a bound introduced by this call | note: required by a bound in `takes_coroutine` - --> $DIR/coroutine-not-future.rs:19:39 + --> $DIR/coroutine-not-future.rs:20:39 | LL | fn takes_coroutine(_g: impl Coroutine) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_coroutine` error[E0277]: `impl Coroutine` is not a future - --> $DIR/coroutine-not-future.rs:43:18 + --> $DIR/coroutine-not-future.rs:44:18 | LL | takes_future(returns_coroutine()); | ------------ ^^^^^^^^^^^^^^^^^^^ `impl Coroutine` is not a future @@ -50,13 +50,13 @@ LL | takes_future(returns_coroutine()); | = help: the trait `Future` is not implemented for `impl Coroutine` note: required by a bound in `takes_future` - --> $DIR/coroutine-not-future.rs:18:26 + --> $DIR/coroutine-not-future.rs:19:26 | LL | fn takes_future(_f: impl Future) {} | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` -error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future - --> $DIR/coroutine-not-future.rs:47:9 +error[E0277]: `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}` is not a future + --> $DIR/coroutine-not-future.rs:48:9 | LL | takes_future( | ------------ required by a bound introduced by this call @@ -65,11 +65,11 @@ LL | / |ctx| { LL | | LL | | ctx = yield (); LL | | }, - | |_________^ `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` is not a future + | |_________^ `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}` is not a future | - = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:47:9: 47:14}` + = help: the trait `Future` is not implemented for `{coroutine@$DIR/coroutine-not-future.rs:48:9: 48:14}` note: required by a bound in `takes_future` - --> $DIR/coroutine-not-future.rs:18:26 + --> $DIR/coroutine-not-future.rs:19:26 | LL | fn takes_future(_f: impl Future) {} | ^^^^^^^^^^^^^^^^^^^ required by this bound in `takes_future` diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr index 694f5a5c1a9da..4c8a5e46751c9 100644 --- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr +++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr @@ -20,10 +20,11 @@ error[E0277]: `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` can't be used as --> $DIR/const_param_ty_bad.rs:8:11 | LL | check(|| {}); - | ----- ^^^^^ the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` + | ----- ^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | + = help: the trait `UnsizedConstParamTy` is not implemented for closure `{closure@$DIR/const_param_ty_bad.rs:8:11: 8:13}` note: required by a bound in `check` --> $DIR/const_param_ty_bad.rs:4:18 | diff --git a/tests/ui/coroutine/clone-impl.rs b/tests/ui/coroutine/clone-impl.rs index 94420e56a2261..b07fad18aee1e 100644 --- a/tests/ui/coroutine/clone-impl.rs +++ b/tests/ui/coroutine/clone-impl.rs @@ -1,6 +1,7 @@ // gate-test-coroutine_clone // Verifies that non-static coroutines can be cloned/copied if all their upvars and locals held // across awaits can be cloned/copied. +//@compile-flags: --diagnostic-width=300 #![feature(coroutines, coroutine_clone, stmt_expr_attributes)] diff --git a/tests/ui/coroutine/clone-impl.stderr b/tests/ui/coroutine/clone-impl.stderr index 1256c97a02fc1..ed933fe784edd 100644 --- a/tests/ui/coroutine/clone-impl.stderr +++ b/tests/ui/coroutine/clone-impl.stderr @@ -1,76 +1,76 @@ -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` - --> $DIR/clone-impl.rs:49:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` + --> $DIR/clone-impl.rs:50:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:47:14 + --> $DIR/clone-impl.rs:48:14 | LL | drop(clonable_0); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:89:18 + --> $DIR/clone-impl.rs:90:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` - --> $DIR/clone-impl.rs:49:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` + --> $DIR/clone-impl.rs:50:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}` ... LL | check_copy(&gen_clone_0); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:43:5: 43:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:44:5: 44:12}`, the trait `Copy` is not implemented for `Vec` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:45:9 + --> $DIR/clone-impl.rs:46:9 | LL | let v = vec!['a']; | - has type `Vec` which does not implement `Copy` LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:89:18 + --> $DIR/clone-impl.rs:90:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` - --> $DIR/clone-impl.rs:70:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}` + --> $DIR/clone-impl.rs:71:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`, the trait `Copy` is not implemented for `Vec` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:68:14 + --> $DIR/clone-impl.rs:69:14 | LL | drop(clonable_1); | ^^^^^^^^^^ has type `Vec` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:89:18 + --> $DIR/clone-impl.rs:90:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` - --> $DIR/clone-impl.rs:70:5 +error[E0277]: the trait bound `Vec: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}` + --> $DIR/clone-impl.rs:71:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}` ... LL | check_copy(&gen_clone_1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:58:5: 58:12}`, the trait `Copy` is not implemented for `Vec` + | ^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:59:5: 59:12}`, the trait `Copy` is not implemented for `Vec` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/clone-impl.rs:64:9 + --> $DIR/clone-impl.rs:65:9 | LL | let v = vec!['a']; | - has type `Vec` which does not implement `Copy` @@ -78,27 +78,27 @@ LL | let v = vec!['a']; LL | yield; | ^^^^^ yield occurs here, with `v` maybe used later note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:89:18 + --> $DIR/clone-impl.rs:90:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` -error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` - --> $DIR/clone-impl.rs:83:5 +error[E0277]: the trait bound `NonClone: Copy` is not satisfied in `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}` + --> $DIR/clone-impl.rs:84:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}` ... LL | check_copy(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Copy` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Copy` is not implemented for `NonClone` | note: captured value does not implement `Copy` - --> $DIR/clone-impl.rs:81:14 + --> $DIR/clone-impl.rs:82:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Copy` note: required by a bound in `check_copy` - --> $DIR/clone-impl.rs:89:18 + --> $DIR/clone-impl.rs:90:18 | LL | fn check_copy(_x: &T) {} | ^^^^ required by this bound in `check_copy` @@ -108,22 +108,22 @@ LL + #[derive(Copy)] LL | struct NonClone; | -error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` - --> $DIR/clone-impl.rs:85:5 +error[E0277]: the trait bound `NonClone: Clone` is not satisfied in `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}` + --> $DIR/clone-impl.rs:86:5 | LL | move || { - | ------- within this `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}` + | ------- within this `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}` ... LL | check_clone(&gen_non_clone); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:79:5: 79:12}`, the trait `Clone` is not implemented for `NonClone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `{coroutine@$DIR/clone-impl.rs:80:5: 80:12}`, the trait `Clone` is not implemented for `NonClone` | note: captured value does not implement `Clone` - --> $DIR/clone-impl.rs:81:14 + --> $DIR/clone-impl.rs:82:14 | LL | drop(non_clonable); | ^^^^^^^^^^^^ has type `NonClone` which does not implement `Clone` note: required by a bound in `check_clone` - --> $DIR/clone-impl.rs:90:19 + --> $DIR/clone-impl.rs:91:19 | LL | fn check_clone(_x: &T) {} | ^^^^^ required by this bound in `check_clone` diff --git a/tests/ui/coroutine/issue-105084.rs b/tests/ui/coroutine/issue-105084.rs index 4e40bc127d780..0f6168ec58b02 100644 --- a/tests/ui/coroutine/issue-105084.rs +++ b/tests/ui/coroutine/issue-105084.rs @@ -1,3 +1,4 @@ +//@compile-flags: --diagnostic-width=300 #![feature(coroutines)] #![feature(coroutine_clone)] #![feature(coroutine_trait)] diff --git a/tests/ui/coroutine/issue-105084.stderr b/tests/ui/coroutine/issue-105084.stderr index 11b5852b638d6..073f1fbea4c63 100644 --- a/tests/ui/coroutine/issue-105084.stderr +++ b/tests/ui/coroutine/issue-105084.stderr @@ -1,8 +1,8 @@ error[E0382]: borrow of moved value: `g` - --> $DIR/issue-105084.rs:38:14 + --> $DIR/issue-105084.rs:39:14 | LL | let mut g = #[coroutine] - | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, which does not implement the `Copy` trait + | ----- move occurs because `g` has type `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, which does not implement the `Copy` trait ... LL | let mut h = copy(g); | - value moved here @@ -11,7 +11,7 @@ LL | Pin::new(&mut g).resume(()); | ^^^^^^ value borrowed here after move | note: consider changing this parameter type in function `copy` to borrow instead if owning the value isn't necessary - --> $DIR/issue-105084.rs:9:21 + --> $DIR/issue-105084.rs:10:21 | LL | fn copy(x: T) -> T { | ---- ^ this parameter takes ownership of the value @@ -22,17 +22,17 @@ help: consider cloning the value if the performance cost is acceptable LL | let mut h = copy(g.clone()); | ++++++++ -error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}` - --> $DIR/issue-105084.rs:32:17 +error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}` + --> $DIR/issue-105084.rs:33:17 | LL | || { - | -- within this `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}` + | -- within this `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}` ... LL | let mut h = copy(g); - | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:15:5: 15:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>` + | ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>` | note: coroutine does not implement `Copy` as this value is used across a yield - --> $DIR/issue-105084.rs:22:22 + --> $DIR/issue-105084.rs:23:22 | LL | Box::new((5, yield)); | -------------^^^^^-- @@ -40,7 +40,7 @@ LL | Box::new((5, yield)); | | yield occurs here, with `Box::new((5, yield))` maybe used later | has type `Box<(i32, ())>` which does not implement `Copy` note: required by a bound in `copy` - --> $DIR/issue-105084.rs:9:12 + --> $DIR/issue-105084.rs:10:12 | LL | fn copy(x: T) -> T { | ^^^^ required by this bound in `copy` diff --git a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index 75a3ae1a83e2f..60d0263c149b4 100644 --- a/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/tests/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -20,10 +20,11 @@ error[E0277]: the trait bound `{closure@$DIR/fn-ctor-passed-as-arg-where-it-shou --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:19:9 | LL | bar(closure); - | --- ^^^^^^^ the trait `T` is not implemented for closure `{closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21}` + | --- ^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | + = help: the trait `T` is not implemented for closure `{closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21}` note: required by a bound in `bar` --> $DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:14:16 | diff --git a/tests/ui/suggestions/issue-84973-blacklist.rs b/tests/ui/suggestions/issue-84973-blacklist.rs index edc0637636b57..7edf4d347af25 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.rs +++ b/tests/ui/suggestions/issue-84973-blacklist.rs @@ -1,5 +1,6 @@ // Checks that certain traits for which we don't want to suggest borrowing // are blacklisted and don't cause the suggestion to be issued. +//@compile-flags: --diagnostic-width=300 #![feature(coroutines)] diff --git a/tests/ui/suggestions/issue-84973-blacklist.stderr b/tests/ui/suggestions/issue-84973-blacklist.stderr index c1ef1cd428e4a..a6324a824c1c3 100644 --- a/tests/ui/suggestions/issue-84973-blacklist.stderr +++ b/tests/ui/suggestions/issue-84973-blacklist.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `String: Copy` is not satisfied - --> $DIR/issue-84973-blacklist.rs:15:12 + --> $DIR/issue-84973-blacklist.rs:16:12 | LL | f_copy("".to_string()); | ------ ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` @@ -7,7 +7,7 @@ LL | f_copy("".to_string()); | required by a bound introduced by this call | note: required by a bound in `f_copy` - --> $DIR/issue-84973-blacklist.rs:6:14 + --> $DIR/issue-84973-blacklist.rs:7:14 | LL | fn f_copy(t: T) {} | ^^^^ required by this bound in `f_copy` @@ -18,7 +18,7 @@ LL + f_copy(""); | error[E0277]: the trait bound `S: Clone` is not satisfied - --> $DIR/issue-84973-blacklist.rs:16:13 + --> $DIR/issue-84973-blacklist.rs:17:13 | LL | f_clone(S); | ------- ^ the trait `Clone` is not implemented for `S` @@ -26,7 +26,7 @@ LL | f_clone(S); | required by a bound introduced by this call | note: required by a bound in `f_clone` - --> $DIR/issue-84973-blacklist.rs:7:15 + --> $DIR/issue-84973-blacklist.rs:8:15 | LL | fn f_clone(t: T) {} | ^^^^^ required by this bound in `f_clone` @@ -36,24 +36,24 @@ LL + #[derive(Clone)] LL | struct S; | -error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}` cannot be unpinned - --> $DIR/issue-84973-blacklist.rs:17:26 +error[E0277]: `{static coroutine@$DIR/issue-84973-blacklist.rs:18:26: 18:35}` cannot be unpinned + --> $DIR/issue-84973-blacklist.rs:18:26 | LL | f_unpin(#[coroutine] static || { yield; }); - | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:17:26: 17:35}` + | ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/issue-84973-blacklist.rs:18:26: 18:35}` | | | required by a bound introduced by this call | = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required by a bound in `f_unpin` - --> $DIR/issue-84973-blacklist.rs:8:15 + --> $DIR/issue-84973-blacklist.rs:9:15 | LL | fn f_unpin(t: T) {} | ^^^^^ required by this bound in `f_unpin` error[E0277]: the size for values of type `dyn Fn()` cannot be known at compilation time - --> $DIR/issue-84973-blacklist.rs:22:13 + --> $DIR/issue-84973-blacklist.rs:23:13 | LL | f_sized(*ref_cl); | ------- ^^^^^^^ doesn't have a size known at compile-time @@ -62,7 +62,7 @@ LL | f_sized(*ref_cl); | = help: the trait `Sized` is not implemented for `dyn Fn()` note: required by a bound in `f_sized` - --> $DIR/issue-84973-blacklist.rs:9:15 + --> $DIR/issue-84973-blacklist.rs:10:15 | LL | fn f_sized(t: T) {} | ^^^^^ required by this bound in `f_sized` @@ -73,7 +73,7 @@ LL + f_sized(ref_cl); | error[E0277]: `Rc<{integer}>` cannot be sent between threads safely - --> $DIR/issue-84973-blacklist.rs:27:12 + --> $DIR/issue-84973-blacklist.rs:28:12 | LL | f_send(rc); | ------ ^^ `Rc<{integer}>` cannot be sent between threads safely @@ -82,7 +82,7 @@ LL | f_send(rc); | = help: the trait `Send` is not implemented for `Rc<{integer}>` note: required by a bound in `f_send` - --> $DIR/issue-84973-blacklist.rs:10:14 + --> $DIR/issue-84973-blacklist.rs:11:14 | LL | fn f_send(t: T) {} | ^^^^ required by this bound in `f_send` diff --git a/tests/ui/traits/fn-pointer/bare-fn-no-impl-fn-ptr-99875.stderr b/tests/ui/traits/fn-pointer/bare-fn-no-impl-fn-ptr-99875.stderr index 0666da4c707d4..5b89158b0dba2 100644 --- a/tests/ui/traits/fn-pointer/bare-fn-no-impl-fn-ptr-99875.stderr +++ b/tests/ui/traits/fn-pointer/bare-fn-no-impl-fn-ptr-99875.stderr @@ -20,10 +20,11 @@ error[E0277]: the trait bound `{closure@$DIR/bare-fn-no-impl-fn-ptr-99875.rs:14: --> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11 | LL | takes(|_: Argument| -> Return { todo!() }); - | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `{closure@$DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11: 14:34}` + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound | | | required by a bound introduced by this call | + = help: the trait `Trait` is not implemented for closure `{closure@$DIR/bare-fn-no-impl-fn-ptr-99875.rs:14:11: 14:34}` = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` note: required by a bound in `takes` --> $DIR/bare-fn-no-impl-fn-ptr-99875.rs:9:18 diff --git a/tests/ui/transmutability/assoc-bound.stderr b/tests/ui/transmutability/assoc-bound.stderr index 08d9089439645..b3c7680bf2949 100644 --- a/tests/ui/transmutability/assoc-bound.stderr +++ b/tests/ui/transmutability/assoc-bound.stderr @@ -2,8 +2,9 @@ error[E0277]: the trait bound `::AssocA: TransmuteFrom<(), Assume { alig --> $DIR/assoc-bound.rs:16:19 | LL | type AssocB = T::AssocA; - | ^^^^^^^^^ the trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `::AssocA` + | ^^^^^^^^^ unsatisfied trait bound | + = help: the trait `TransmuteFrom<(), Assume { alignment: false, lifetimes: false, safety: false, validity: false }>` is not implemented for `::AssocA` note: required by a bound in `B::AssocB` --> $DIR/assoc-bound.rs:9:18 | diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index bb99f4ad27762..0d8ec5f892894 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -2,8 +2,9 @@ error[E0277]: the trait bound `for $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^^^ the trait `for Foo` is not implemented for `fn(&'^1_0.Named(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), "'b") ())` + | ^^^^^^^^ unsatisfied trait bound | + = help: the trait `for Foo` is not implemented for `fn(&'^1_0.Named(DefId(0:6 ~ higher_ranked_fn_type[9e51]::called::'b), "'b") ())` help: this trait has no implementations, consider adding one --> $DIR/higher-ranked-fn-type.rs:6:1 | From 083d70f6cc746827a7fe179005a657de0464ce23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Oct 2024 22:54:42 +0000 Subject: [PATCH 15/16] Account for negative bounds in E0277 note and suggestion Do not suggest `#[derive(Copy)]` when we wanted a `!Copy` type. Do not say "`Copy` is not implemented for `T` but `Copy` is". Do not talk about `Trait` having no implementations when `!Trait` was desired. --- .../src/error_reporting/traits/fulfillment_errors.rs | 6 +++++- .../src/error_reporting/traits/suggestions.rs | 3 +++ .../traits/negative-bounds/on-unimplemented.stderr | 6 ------ tests/ui/traits/negative-bounds/simple.stderr | 12 ------------ 4 files changed, 8 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index cef704d832810..524b413960095 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2540,12 +2540,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && self.tcx.trait_impls_of(trait_def_id).is_empty() && !self.tcx.trait_is_auto(trait_def_id) && !self.tcx.trait_is_alias(trait_def_id) + && trait_predicate.polarity() == ty::PredicatePolarity::Positive { err.span_help( self.tcx.def_span(trait_def_id), crate::fluent_generated::trait_selection_trait_has_no_impls, ); - } else if !suggested && !unsatisfied_const { + } else if !suggested + && !unsatisfied_const + && trait_predicate.polarity() == ty::PredicatePolarity::Positive + { // Can't show anything else useful, try to find similar impls. let impl_candidates = self.find_similar_impl_candidates(trait_predicate); if !self.report_similar_impl_candidates( diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 64edeb35dd257..68aa9cffef207 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3697,6 +3697,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err: &mut Diag<'_>, trait_pred: ty::PolyTraitPredicate<'tcx>, ) { + if trait_pred.polarity() == ty::PredicatePolarity::Negative { + return; + } let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) else { return; }; diff --git a/tests/ui/traits/negative-bounds/on-unimplemented.stderr b/tests/ui/traits/negative-bounds/on-unimplemented.stderr index 07483e788e5b8..ed473d5791737 100644 --- a/tests/ui/traits/negative-bounds/on-unimplemented.stderr +++ b/tests/ui/traits/negative-bounds/on-unimplemented.stderr @@ -6,12 +6,6 @@ LL | fn hello() -> impl !Foo { LL | LL | NotFoo | ------ return type was inferred to be `NotFoo` here - | -help: this trait has no implementations, consider adding one - --> $DIR/on-unimplemented.rs:4:1 - | -LL | trait Foo {} - | ^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-bounds/simple.stderr b/tests/ui/traits/negative-bounds/simple.stderr index f8a43e605c477..499c19bb85468 100644 --- a/tests/ui/traits/negative-bounds/simple.stderr +++ b/tests/ui/traits/negative-bounds/simple.stderr @@ -28,18 +28,11 @@ error[E0277]: the trait bound `Copyable: !Copy` is not satisfied LL | not_copy::(); | ^^^^^^^^ the trait bound `Copyable: !Copy` is not satisfied | - = help: the trait `Copy` is not implemented for `Copyable` - but trait `Copy` is implemented for it note: required by a bound in `not_copy` --> $DIR/simple.rs:3:16 | LL | fn not_copy() {} | ^^^^^ required by this bound in `not_copy` -help: consider annotating `Copyable` with `#[derive(Copy)]` - | -LL + #[derive(Copy)] -LL | struct Copyable; - | error[E0277]: the trait bound `NotNecessarilyCopyable: !Copy` is not satisfied --> $DIR/simple.rs:37:16 @@ -52,11 +45,6 @@ note: required by a bound in `not_copy` | LL | fn not_copy() {} | ^^^^^ required by this bound in `not_copy` -help: consider annotating `NotNecessarilyCopyable` with `#[derive(Copy)]` - | -LL + #[derive(Copy)] -LL | struct NotNecessarilyCopyable; - | error: aborting due to 4 previous errors From e4305f16570efc342529e35c7b0ec5b1ca50b954 Mon Sep 17 00:00:00 2001 From: Noratrieb <48135649+Noratrieb@users.noreply.github.com> Date: Fri, 1 Nov 2024 20:10:36 +0100 Subject: [PATCH 16/16] Add a bunch of mailmap entries This adds a bunch of missing mailmap entries for many people. These are needed when using rust-lang/team information in rust-lang/thanks, as the emails there may differ. These are all the "easy" ones, where there was a mailmap entry already, making it clear which one is the preferred email address. --- .mailmap | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index 56490ca5059b0..fdb62a9d77826 100644 --- a/.mailmap +++ b/.mailmap @@ -31,6 +31,7 @@ Alexis Beingessner Alfie John Alfie John Alona Enraght-Moony Alona Enraght-Moony +Alona Enraght-Moony Amanda Stjerna Amanda Stjerna Amos Onn @@ -75,6 +76,7 @@ Benjamin Jackman Benoît Cortier Bheesham Persaud Bheesham Persaud bjorn3 <17426603+bjorn3@users.noreply.github.com> +bjorn3 <17426603+bjorn3@users.noreply.github.com> Björn Steinbrink blake2-ppc blyxyas Alejandra González @@ -172,6 +174,7 @@ Dzmitry Malyshau E. Dunham edunham Ed Barnard Eduard-Mihai Burtescu +Eduard-Mihai Burtescu Eduardo Bautista <=> Eduardo Bautista Eduardo Broto @@ -186,6 +189,7 @@ Erick Tryzelaar Erik Desjardins Erik Jensen Erin Power +Erin Power Erin Power Erin Power Esteban Küber @@ -198,6 +202,7 @@ F001 Fabian Kössel Falco Hirschenberger Felix S. Klock II Felix S Klock II +Felix S. Klock II Félix Saparelli Flaper Fesp Florian Berger @@ -245,7 +250,7 @@ Irina Popa Ivan Ivaschenko ivan tkachenko J. J. Weber -Jack Huey +Jack Huey Jacob Jacob Greenfield Jacob Pratt @@ -292,6 +297,7 @@ John Clements John Hodge John Hodge John Hörnvall John Kåre Alsaker +John Kåre Alsaker John Talling John Van Enk Jonas Tepe @@ -368,6 +374,7 @@ Lukas Lueg Luke Metz Luqman Aden Luqman Aden +Luqman Aden Lzu Tao Maik Klein Malo Jaffré @@ -409,6 +416,7 @@ mental mibac138 <5672750+mibac138@users.noreply.github.com> Michael Williams Michael Woerister +Michael Woerister Michael Woerister Michael Woerister Michael Zhang @@ -422,6 +430,7 @@ Ms2ger msizanoen1 Mukilan Thiagarajan Nadrieril Feneanar +Nadrieril Feneanar NAKASHIMA, Makoto NAKASHIMA, Makoto Nathan Ringo @@ -442,6 +451,8 @@ Niclas Schwarzlose <15schnic@gmail.com> Nicolas Abram Nicole Mazzuca Noratrieb <48135649+Noratrieb@users.noreply.github.com> <48135649+Nilstrieb@users.noreply.github.com> +Noratrieb <48135649+Noratrieb@users.noreply.github.com> +Noratrieb <48135649+Noratrieb@users.noreply.github.com> Nif Ward Nika Layzell NODA Kai @@ -460,6 +471,7 @@ Oliver Scherer Oliver Scherer Oliver Scherer Oliver Scherer +Oliver Scherer Oliver Scherer Onur Özkan Onur Özkan @@ -496,6 +508,7 @@ Raphaël Huchet rChaser53 Rémy Rakic Rémy Rakic +Rémy Rakic Renato Riccieri Santos Zannon Richard Diamond Ricky Hosfelt @@ -525,6 +538,7 @@ Samuel Tardieu Santiago Pastorino Santiago Pastorino Scott McMurray +Scott McMurray Scott Olson Scott Olson Sean Gillespie swgillespie Seiichi Uchida @@ -536,6 +550,7 @@ Shyam Sundar B Simon Barber-Dueck Simon BD Simon Sapin Simonas Kazlauskas Simonas Kazlauskas +Simonas Kazlauskas Siva Prasad Smittyvb Srinivas Reddy Thatiparthy @@ -556,6 +571,8 @@ Tatsuyuki Ishi Tau Gärtli Tero Hänninen Tero Hänninen The8472 +The8472 +The8472 Theo Belaire Theo Belaire Theodore Luo Wang Thiago Pontes thiagopnts @@ -593,7 +610,8 @@ Waffle Lapkin Wesley Wiser whitequark William Ting -Wim Looman +Wim Looman +Wim Looman Without Boats Without Boats Xinye Tao