From 72a9029b84d0c2dcf10cee08d39f8a64964df22d Mon Sep 17 00:00:00 2001 From: Joshua Liebow-Feeser Date: Sun, 6 Nov 2022 16:08:05 -0800 Subject: [PATCH 01/32] PhantomData layout guarantees --- library/core/src/marker.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index ae4ebf4444295..26b7dddcd2e58 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -621,6 +621,12 @@ impl !Sync for *mut T {} /// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so /// as not to indicate ownership. /// +/// ## Layout +/// +/// For all `T`, the following are guaranteed: +/// * `size_of::>() == 0` +/// * `align_of::>() == 1` +/// /// [drop check]: ../../nomicon/dropck.html #[lang = "phantom_data"] #[stable(feature = "rust1", since = "1.0.0")] From ac583f18b75f005023b41d49298d4d343740648a Mon Sep 17 00:00:00 2001 From: Markus Everling Date: Thu, 1 Dec 2022 12:21:12 +0100 Subject: [PATCH 02/32] Add O(1) `Vec -> VecDeque` conversion guarantee --- library/alloc/src/collections/vec_deque/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 4866c53e7d521..0645f2ae4da85 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -2794,9 +2794,9 @@ impl From> for VecDeque { /// [`Vec`]: crate::vec::Vec /// [`VecDeque`]: crate::collections::VecDeque /// - /// In its current implementation, this is a very cheap - /// conversion. This isn't yet a guarantee though, and - /// shouldn't be relied on. + /// This conversion is guaranteed to run in *O*(1) time + /// and to not re-allocate the `Vec`'s buffer or allocate + /// any additional memory. #[inline] fn from(other: Vec) -> Self { let (ptr, len, cap, alloc) = other.into_raw_parts_with_alloc(); From 9553a4d439ffcf239c12142a78aa9923058e8a78 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 9 Dec 2022 17:23:09 -0800 Subject: [PATCH 03/32] Fix process-panic-after-fork.rs to pass on newer versions of Android. The test process-panic-after-fork.rs was checking that abort() resulted in SIGSEGV on Android. This non-standard behavior was fixed back in 2013, so let's fix the test to also accept the standard behavior on Android. --- .../ui/process/process-panic-after-fork.rs | 77 ++++++++++--------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/src/test/ui/process/process-panic-after-fork.rs b/src/test/ui/process/process-panic-after-fork.rs index 6d4d24922253d..da2683121735f 100644 --- a/src/test/ui/process/process-panic-after-fork.rs +++ b/src/test/ui/process/process-panic-after-fork.rs @@ -84,42 +84,47 @@ fn expect_aborted(status: ExitStatus) { #[cfg(target_os = "android")] { - // Android signals an abort() call with SIGSEGV at address 0xdeadbaad - // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc - assert!(signal == libc::SIGSEGV); - - // Additional checks performed: - // 1. Find last tombstone (similar to coredump but in text format) from the - // same executable (path) as we are (must be because of usage of fork): - // This ensures that we look into the correct tombstone. - // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad. - // 3. libc::abort call is in one of top two functions on callstack. - // The last two steps distinguish between a normal SIGSEGV and one caused - // by libc::abort. - - let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap(); - let exe_string = format!(">>> {this_exe} <<<"); - let tombstone = (0..100) - .map(|n| format!("/data/tombstones/tombstone_{n:02}")) - .filter(|f| std::path::Path::new(&f).exists()) - .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file")) - .filter(|f| f.contains(&exe_string)) - .last() - .expect("no tombstone found"); - - println!("Content of tombstone:\n{tombstone}"); - - assert!( - tombstone.contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad") - ); - let abort_on_top = tombstone - .lines() - .skip_while(|l| !l.contains("backtrace:")) - .skip(1) - .take_while(|l| l.starts_with(" #")) - .take(2) - .any(|f| f.contains("/system/lib/libc.so (abort")); - assert!(abort_on_top); + assert!(signal == libc::SIGABRT || signal == libc::SIGSEGV); + + if signal == libc::SIGSEGV { + // Pre-KitKat versions of Android signal an abort() with SIGSEGV at address 0xdeadbaad + // See e.g. https://groups.google.com/g/android-ndk/c/laW1CJc7Icc + // + // This behavior was changed in KitKat to send a standard SIGABRT signal. + // See: https://r.android.com/60341 + // + // Additional checks performed: + // 1. Find last tombstone (similar to coredump but in text format) from the + // same executable (path) as we are (must be because of usage of fork): + // This ensures that we look into the correct tombstone. + // 2. Cause of crash is a SIGSEGV with address 0xdeadbaad. + // 3. libc::abort call is in one of top two functions on callstack. + // The last two steps distinguish between a normal SIGSEGV and one caused + // by libc::abort. + + let this_exe = std::env::current_exe().unwrap().into_os_string().into_string().unwrap(); + let exe_string = format!(">>> {this_exe} <<<"); + let tombstone = (0..100) + .map(|n| format!("/data/tombstones/tombstone_{n:02}")) + .filter(|f| std::path::Path::new(&f).exists()) + .map(|f| std::fs::read_to_string(&f).expect("Cannot read tombstone file")) + .filter(|f| f.contains(&exe_string)) + .last() + .expect("no tombstone found"); + + println!("Content of tombstone:\n{tombstone}"); + + assert!(tombstone + .contains("signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr deadbaad")); + let abort_on_top = tombstone + .lines() + .skip_while(|l| !l.contains("backtrace:")) + .skip(1) + .take_while(|l| l.starts_with(" #")) + .take(2) + .any(|f| f.contains("/system/lib/libc.so (abort")); + assert!(abort_on_top); + } } } From 5cccb36cfbc887da04dc367c24d2b4947c993ff9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 18 Dec 2022 03:04:21 +0000 Subject: [PATCH 04/32] higher-ranked lifetime message --- compiler/rustc_resolve/src/late.rs | 27 ++++++++++++++----- src/test/ui/error-codes/E0637.stderr | 6 +++++ ...rrect-explicit-lifetime-name-needed.stderr | 6 +++++ ...se-inherent-impl-ampersand.rust2015.stderr | 6 +++++ ...se-inherent-impl-ampersand.rust2018.stderr | 6 +++++ ...e-clause-trait-impl-region.rust2015.stderr | 6 +++++ ...e-clause-trait-impl-region.rust2018.stderr | 6 +++++ 7 files changed, 57 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 5b7a00101e9b7..ef0f41223eab5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1512,7 +1512,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { count: 1, }; let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime); - for rib in self.lifetime_ribs.iter().rev() { + for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() { debug!(?rib.kind); match rib.kind { LifetimeRibKind::AnonymousCreateParameter { binder, .. } => { @@ -1529,16 +1529,31 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } else { ("`'_` cannot be used here", "`'_` is a reserved lifetime name") }; - rustc_errors::struct_span_err!( + let mut diag = rustc_errors::struct_span_err!( self.r.session, lifetime.ident.span, E0637, "{}", msg, - ) - .span_label(lifetime.ident.span, note) - .emit(); - + ); + diag.span_label(lifetime.ident.span, note); + if elided { + for rib in self.lifetime_ribs[i..].iter().rev() { + if let LifetimeRibKind::Generics { + span, + kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound, + .. + } = &rib.kind + { + diag.span_help( + *span, + "consider introducing a higher-ranked lifetime here with `for<'a>`", + ); + break; + } + } + } + diag.emit(); self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate); return; } diff --git a/src/test/ui/error-codes/E0637.stderr b/src/test/ui/error-codes/E0637.stderr index 35a4b34fb0a4d..78341735e191a 100644 --- a/src/test/ui/error-codes/E0637.stderr +++ b/src/test/ui/error-codes/E0637.stderr @@ -21,6 +21,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: Into<&u32>, | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/E0637.rs:13:8 + | +LL | T: Into<&u32>, + | ^ error: aborting due to 3 previous errors diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr index e45387acaf31d..9d859fddf56b4 100644 --- a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | fn should_error() where T : Into<&u32> {} | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32 + | +LL | fn should_error() where T : Into<&u32> {} + | ^ error[E0106]: missing lifetime specifier --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20 diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr index fe726cb49c737..f4d14b5f87bec 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2015.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr index fe726cb49c737..f4d14b5f87bec 100644 --- a/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-inherent-impl-ampersand.rust2018.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-inherent-impl-ampersand.rs:13:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr index fbd14de21078b..63fc1a19b9383 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2015.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr index fbd14de21078b..63fc1a19b9383 100644 --- a/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr +++ b/src/test/ui/underscore-lifetime/where-clause-trait-impl-region.rust2018.stderr @@ -3,6 +3,12 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here | LL | T: WithType<&u32> | ^ explicit lifetime name needed here + | +help: consider introducing a higher-ranked lifetime here with `for<'a>` + --> $DIR/where-clause-trait-impl-region.rs:11:8 + | +LL | T: WithType<&u32> + | ^ error: aborting due to previous error From 82cf6f204aeb791c38463798e2edd6b4935f1296 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Wed, 16 Nov 2022 20:08:14 -0500 Subject: [PATCH 05/32] UPDATE - migrate base.rs to new diagnostics infrastructure --- compiler/rustc_codegen_ssa/src/base.rs | 16 +++++---------- compiler/rustc_codegen_ssa/src/errors.rs | 20 +++++++++++++++++++ .../locales/en-US/codegen_ssa.ftl | 7 +++++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8b34be3858006..d318c15d34221 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -5,6 +5,7 @@ use crate::back::write::{ submit_post_lto_module_to_llvm, submit_pre_lto_module_to_llvm, ComputedLtoType, OngoingCodegen, }; use crate::common::{IntPredicate, RealPredicate, TypeKind}; +use crate::errors; use crate::meth; use crate::mir; use crate::mir::operand::OperandValue; @@ -451,10 +452,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let Some(llfn) = cx.declare_c_main(llfty) else { // FIXME: We should be smart and show a better diagnostic here. let span = cx.tcx().def_span(rust_main_def_id); - cx.sess() - .struct_span_err(span, "entry symbol `main` declared multiple times") - .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") - .emit(); + cx.sess().emit_err(errors::MultipleMainFunctions { span }); cx.sess().abort_if_errors(); bug!(); }; @@ -595,8 +593,8 @@ pub fn codegen_crate( &metadata, &exported_symbols::metadata_symbol_name(tcx), ); - if let Err(err) = std::fs::write(&file_name, data) { - tcx.sess.fatal(&format!("error writing metadata object file: {}", err)); + if let Err(error) = std::fs::write(&file_name, data) { + tcx.sess.emit_fatal(errors::MetadataObjectFileWrite { error }); } Some(CompiledModule { name: metadata_cgu_name, @@ -815,11 +813,7 @@ impl CrateInfo { let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != sym::windows && subsystem != sym::console { - tcx.sess.fatal(&format!( - "invalid windows subsystem `{}`, only \ - `windows` and `console` are allowed", - subsystem - )); + tcx.sess.emit_fatal(errors::InvalidWindowsSubsystem { subsystem }); } subsystem.to_string() }); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 0620000201f02..9179fe03d3f62 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -555,3 +555,23 @@ pub struct ExpectedUsedSymbol { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_multiple_main_functions)] +#[help] +pub struct MultipleMainFunctions { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_metadata_object_file_write)] +pub struct MetadataObjectFileWrite { + pub error: Error, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_invalid_windows_subsystem)] +pub struct InvalidWindowsSubsystem { + pub subsystem: Symbol, +} diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index db4c82b35c778..1863dae258ffa 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -194,3 +194,10 @@ codegen_ssa_unknown_archive_kind = Don't know how to build archive of type: {$kind} codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` + +codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times + .help = did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + +codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} + +codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed From 78796ba637d9c8b575e977ddfc9351e4f1626319 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 5 Nov 2022 23:54:42 -0400 Subject: [PATCH 06/32] ADD - fixme in type_names.rs until we are able to translate InterpError --- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 3ae6c531b4453..1599ccbb2594c 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -93,6 +93,7 @@ fn push_debuginfo_type_name<'tcx>( Err(e) => { // Computing the layout can still fail here, e.g. if the target architecture // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961. + // FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable. tcx.sess.fatal(&format!("{}", e)); } } From d41112a8c5f0b85649b4f0e1663edf15f7f2601e Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 6 Nov 2022 10:09:24 -0500 Subject: [PATCH 07/32] UPDATE - migrate constant.rs to new diagnostics infrastructure --- compiler/rustc_codegen_ssa/src/errors.rs | 14 ++++++++++++++ compiler/rustc_codegen_ssa/src/mir/constant.rs | 5 +++-- .../locales/en-US/codegen_ssa.ftl | 4 ++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 9179fe03d3f62..de0a80280be9c 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -575,3 +575,17 @@ pub struct MetadataObjectFileWrite { pub struct InvalidWindowsSubsystem { pub subsystem: Symbol, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_erroneous_constant)] +pub struct ErroneousConstant { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(codegen_ssa_shuffle_indices_evaluation)] +pub struct ShuffleIndicesEvaluation { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 53ff3c2409626..3cae19b241d62 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,3 +1,4 @@ +use crate::errors; use crate::mir::operand::OperandRef; use crate::traits::*; use rustc_middle::mir; @@ -44,7 +45,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| { match err { ErrorHandled::Reported(_) => { - self.cx.tcx().sess.span_err(constant.span, "erroneous constant encountered"); + self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span }); } ErrorHandled::TooGeneric => { span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err); @@ -87,7 +88,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (llval, c.ty()) }) .unwrap_or_else(|_| { - bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time"); + bx.tcx().sess.emit_err(errors::ShuffleIndicesEvaluation { span }); // We've errored, so we don't have to produce working code. let ty = self.monomorphize(ty); let llty = bx.backend_type(bx.layout_of(ty)); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 1863dae258ffa..88fb7ce8d9f79 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -201,3 +201,7 @@ codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple time codegen_ssa_metadata_object_file_write = error writing metadata object file: {$error} codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed + +codegen_ssa_erroneous_constant = erroneous constant encountered + +codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time From e26366ad99a6da4df5c9b476eff00c48e50d1774 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sun, 13 Nov 2022 14:03:22 -0500 Subject: [PATCH 08/32] [WIP] UPDATE - migrate intrinsic.rs to new diagnostic infrastructure WIP - replacing span_invalid_monomorphization_error function. Still in progress due to its use in codegen_llvm inside macros --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 13 ++-- compiler/rustc_codegen_ssa/src/errors.rs | 43 +++++++++++++ .../rustc_codegen_ssa/src/mir/intrinsic.rs | 64 ++++--------------- .../locales/en-US/codegen_ssa.ftl | 14 ++++ 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1ce48f82e1c9b..82c6c38949478 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -10,6 +10,7 @@ use crate::value::Value; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; +use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; @@ -284,15 +285,11 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - tcx.sess, + tcx.sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + name, + ty, + }); return; } } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index de0a80280be9c..7303ab9679759 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -6,6 +6,7 @@ use rustc_errors::{ IntoDiagnosticArg, }; use rustc_macros::Diagnostic; +use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; use std::borrow::Cow; use std::io::Error; @@ -589,3 +590,45 @@ pub struct ShuffleIndicesEvaluation { #[primary_span] pub span: Span, } + +#[derive(Diagnostic)] +#[diag(codegen_ssa_missing_memory_ordering)] +pub struct MissingMemoryOrdering; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_atomic_ordering)] +pub struct UnknownAtomicOrdering; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_atomic_compare_exchange)] +pub struct AtomicCompareExchange; + +#[derive(Diagnostic)] +#[diag(codegen_ssa_unknown_atomic_operation)] +pub struct UnknownAtomicOperation; + +#[derive(Diagnostic)] +pub enum InvalidMonomorphization<'tcx> { + #[diag(codegen_ssa_invalid_monomorphization_basic_integer_type, code = "E0511")] + BasicIntegerType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = "E0511")] + BasicFloatType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_float_to_int_unchecked, code = "E0511")] + FloatToIntUnchecked { + #[primary_span] + span: Span, + ty: Ty<'tcx>, + }, +} diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index a75609260eda4..766dc74cbbb6a 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,7 +1,9 @@ use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; use super::FunctionCx; -use crate::common::{span_invalid_monomorphization_error, IntPredicate}; +use crate::common::IntPredicate; +use crate::errors; +use crate::errors::InvalidMonomorphization; use crate::glue; use crate::meth; use crate::traits::*; @@ -305,15 +307,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); return; } } @@ -329,15 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => bug!(), }, None => { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic float type, found `{}`", - name, arg_tys[0] - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicFloatType { span, name, ty: arg_tys[0] }); return; } } @@ -345,29 +331,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { sym::float_to_int_unchecked => { if float_type_width(arg_tys[0]).is_none() { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ - intrinsic: expected basic float type, \ - found `{}`", - arg_tys[0] - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: arg_tys[0] }); return; } let Some((_width, signed)) = int_type_width_signed(ret_ty, bx.tcx()) else { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `float_to_int_unchecked` \ - intrinsic: expected basic integer type, \ - found `{}`", - ret_ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::FloatToIntUnchecked { span, ty: ret_ty }); return; }; if signed { @@ -402,7 +370,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { use crate::common::{AtomicRmwBinOp, SynchronizationScope}; let Some((instruction, ordering)) = atomic.split_once('_') else { - bx.sess().fatal("Atomic intrinsic missing memory ordering"); + bx.sess().emit_fatal(errors::MissingMemoryOrdering); }; let parse_ordering = |bx: &Bx, s| match s { @@ -412,25 +380,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "release" => Release, "acqrel" => AcquireRelease, "seqcst" => SequentiallyConsistent, - _ => bx.sess().fatal("unknown ordering in atomic intrinsic"), + _ => bx.sess().emit_fatal(errors::UnknownAtomicOrdering), }; let invalid_monomorphization = |ty| { - span_invalid_monomorphization_error( - bx.tcx().sess, - span, - &format!( - "invalid monomorphization of `{}` intrinsic: \ - expected basic integer type, found `{}`", - name, ty - ), - ); + bx.tcx().sess.emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty }); }; match instruction { "cxchg" | "cxchgweak" => { let Some((success, failure)) = ordering.split_once('_') else { - bx.sess().fatal("Atomic compare-exchange intrinsic missing failure memory ordering"); + bx.sess().emit_fatal(errors::AtomicCompareExchange); }; let ty = substs.type_at(0); if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() { @@ -529,7 +489,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "min" => AtomicRmwBinOp::AtomicMin, "umax" => AtomicRmwBinOp::AtomicUMax, "umin" => AtomicRmwBinOp::AtomicUMin, - _ => bx.sess().fatal("unknown atomic operation"), + _ => bx.sess().emit_fatal(errors::UnknownAtomicOperation), }; let ty = substs.type_at(0); diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 88fb7ce8d9f79..889d290037190 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -205,3 +205,17 @@ codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}` codegen_ssa_erroneous_constant = erroneous constant encountered codegen_ssa_shuffle_indices_evaluation = could not evaluate shuffle_indices at compile time + +codegen_ssa_missing_memory_ordering = Atomic intrinsic missing memory ordering + +codegen_ssa_unknown_atomic_ordering = unknown ordering in atomic intrinsic + +codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing failure memory ordering + +codegen_ssa_unknown_atomic_operation = unknown atomic operation + +codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` From d1030fab229d25d3ca14b1aaa2fc8e5a6ec932a8 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Thu, 17 Nov 2022 08:53:14 -0500 Subject: [PATCH 09/32] UPDATE - migrate fn simd_simple_float_intrinsic error messages --- Cargo.lock | 2 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 41 ++++++------------- compiler/rustc_codegen_ssa/Cargo.toml | 1 + compiler/rustc_codegen_ssa/src/errors.rs | 25 +++++++++++ .../locales/en-US/codegen_ssa.ftl | 6 +++ compiler/rustc_errors/Cargo.toml | 1 + compiler/rustc_errors/src/diagnostic_impls.rs | 7 ++++ 7 files changed, 55 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97148641670f4..6f630b479ed2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3636,6 +3636,7 @@ dependencies = [ "rustc_span", "rustc_symbol_mangling", "rustc_target", + "rustc_type_ir", "serde_json", "smallvec", "snap", @@ -3770,6 +3771,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "serde", "serde_json", "termcolor", diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 82c6c38949478..032063d23b6d9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1165,42 +1165,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { - #[allow(unused_macro_rules)] - macro_rules! emit_error { - ($msg: tt) => { - emit_error!($msg, ) - }; - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } - macro_rules! return_error { - ($($fmt: tt)*) => { - { - emit_error!($($fmt)*); - return Err(()); - } - } - } - let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), _ => { - return_error!( - "unsupported element type `{}` of floating-point vector `{}`", - f.name_str(), - in_ty - ); + bx.sess().emit_err(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty, + }); + return Err(()); } } } else { - return_error!("`{}` is not a floating-point type", in_ty); + bx.sess().emit_err(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); + return Err(()); }; let vec_ty = bx.type_vector(elem_ty, in_len); @@ -1222,7 +1204,10 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), - _ => return_error!("unrecognized intrinsic `{}`", name), + _ => { + bx.sess().emit_err(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }); + return Err(()); + } }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml index 345174fb595ab..d1ad687e6aee3 100644 --- a/compiler/rustc_codegen_ssa/Cargo.toml +++ b/compiler/rustc_codegen_ssa/Cargo.toml @@ -27,6 +27,7 @@ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_span = { path = "../rustc_span" } rustc_middle = { path = "../rustc_middle" } +rustc_type_ir = { path = "../rustc_type_ir" } rustc_attr = { path = "../rustc_attr" } rustc_symbol_mangling = { path = "../rustc_symbol_mangling" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 7303ab9679759..5ecba6925fabf 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -8,6 +8,7 @@ use rustc_errors::{ use rustc_macros::Diagnostic; use rustc_middle::ty::Ty; use rustc_span::{Span, Symbol}; +use rustc_type_ir::FloatTy; use std::borrow::Cow; use std::io::Error; use std::path::{Path, PathBuf}; @@ -631,4 +632,28 @@ pub enum InvalidMonomorphization<'tcx> { span: Span, ty: Ty<'tcx>, }, + + #[diag(codegen_ssa_invalid_monomorphization_floating_point_vector, code = "E0511")] + FloatingPointVector { + #[primary_span] + span: Span, + name: Symbol, + f_ty: FloatTy, + in_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_floating_point_type, code = "E0511")] + FloatingPointType { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unrecognized_intrinsic, code = "E0511")] + UnrecognizedIntrinsic { + #[primary_span] + span: Span, + name: Symbol, + }, } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 889d290037190..0d9a9d851fc66 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -219,3 +219,9 @@ codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphizati codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}` codegen_ssa_invalid_monomorphization_float_to_int_unchecked = invalid monomorphization of `float_to_int_unchecked` intrinsic: expected basic float type, found `{$ty}` + +codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphization of `{$name}` intrinsic: unsupported element type `{$f_ty}` of floating-point vector `{$in_ty}` + +codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type + +codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index dee7a31ec2028..cadd53fbd8356 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -17,6 +17,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_target = { path = "../rustc_target" } rustc_hir = { path = "../rustc_hir" } rustc_lint_defs = { path = "../rustc_lint_defs" } +rustc_type_ir = { path = "../rustc_type_ir" } unicode-width = "0.1.4" termcolor = "1.0" annotate-snippets = "0.9" diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 628cb90903fee..794b6efcc2b24 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -9,6 +9,7 @@ use rustc_span::edition::Edition; use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_target::abi::TargetDataLayoutErrors; use rustc_target::spec::{PanicStrategy, SplitDebuginfo, StackProtector, TargetTriple}; +use rustc_type_ir as type_ir; use std::borrow::Cow; use std::fmt; use std::num::ParseIntError; @@ -170,6 +171,12 @@ impl IntoDiagnosticArg for ast::token::TokenKind { } } +impl IntoDiagnosticArg for type_ir::FloatTy { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + DiagnosticArgValue::Str(Cow::Borrowed(self.name_str())) + } +} + impl IntoDiagnosticArg for Level { fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { DiagnosticArgValue::Str(Cow::Borrowed(match self { From 27744460e2d0b960a55a28637ba46835484e4335 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Wed, 23 Nov 2022 01:07:36 -0500 Subject: [PATCH 10/32] ADD - create and emit Bug support for Diagnostics UPDATE - migrate constant span_bug to translatable diagnostic. --- compiler/rustc_codegen_ssa/src/errors.rs | 7 +++ .../rustc_codegen_ssa/src/mir/constant.rs | 6 +- .../locales/en-US/codegen_ssa.ftl | 2 + .../rustc_errors/src/diagnostic_builder.rs | 55 ++++++++++++++++++- compiler/rustc_errors/src/lib.rs | 14 +++++ 5 files changed, 82 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 5ecba6925fabf..852925a1787c8 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -585,6 +585,13 @@ pub struct ErroneousConstant { pub span: Span, } +#[derive(Diagnostic)] +#[diag(codegen_ssa_polymorphic_constant_too_generic)] +pub struct PolymorphicConstantTooGeneric { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(codegen_ssa_shuffle_indices_evaluation)] pub struct ShuffleIndicesEvaluation { diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 3cae19b241d62..14fe84a146da0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -48,7 +48,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span }); } ErrorHandled::TooGeneric => { - span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err); + self.cx + .tcx() + .sess + .diagnostic() + .emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span }); } } err diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index 0d9a9d851fc66..d10c399bb6afc 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -225,3 +225,5 @@ codegen_ssa_invalid_monomorphization_floating_point_vector = invalid monomorphiz codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphization of `{$name}` intrinsic: `{$in_ty}` is not a floating-point type codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` + +codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index a2ed988643ff2..cbfee582d871f 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -1,7 +1,7 @@ use crate::diagnostic::IntoDiagnosticArg; use crate::{ Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed, - SubdiagnosticMessage, + ExplicitBug, SubdiagnosticMessage, }; use crate::{Handler, Level, MultiSpan, StashKey}; use rustc_lint_defs::Applicability; @@ -12,6 +12,7 @@ use std::borrow::Cow; use std::fmt::{self, Debug}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; +use std::panic; use std::thread::panicking; /// Trait implemented by error types. This should not be implemented manually. Instead, use @@ -308,6 +309,58 @@ impl EmissionGuarantee for Noted { } } +/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for +/// bug struct diagnostics. +#[derive(Copy, Clone)] +pub struct Bug; + +impl<'a> DiagnosticBuilder<'a, Bug> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + #[track_caller] + pub(crate) fn new_bug(handler: &'a Handler, message: impl Into) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message); + Self::new_diagnostic_bug(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic bug"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for Bug { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + // Then panic. No need to return the marker type. + panic::panic_any(ExplicitBug); + } + + fn make_diagnostic_builder( + handler: &Handler, + msg: impl Into, + ) -> DiagnosticBuilder<'_, Self> { + DiagnosticBuilder::new_bug(handler, msg) + } +} + impl<'a> DiagnosticBuilder<'a, !> { /// Convenience function for internal use, clients should use one of the /// `struct_*` methods on [`Handler`]. diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b03352d5fec6b..cf9741366a18b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1127,6 +1127,20 @@ impl Handler { self.create_fatal(fatal).emit() } + pub fn create_bug<'a>( + &'a self, + bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, + ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { + bug.into_diagnostic(self) + } + + pub fn emit_bug<'a>( + &'a self, + bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, + ) -> diagnostic_builder::Bug { + self.create_bug(bug).emit() + } + fn emit_diag_at_span( &self, mut diag: Diagnostic, From 29d8c87fe88f51bdc7e6197e2e8eed7adc898f49 Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 26 Nov 2022 20:28:01 -0500 Subject: [PATCH 11/32] DELETE - fn span_invalid_monomorphization_error and localize intrinsics macros --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 529 ++++++++++-------- compiler/rustc_codegen_ssa/src/common.rs | 6 - compiler/rustc_codegen_ssa/src/errors.rs | 322 +++++++++++ .../locales/en-US/codegen_ssa.ftl | 66 +++ 4 files changed, 670 insertions(+), 253 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 032063d23b6d9..680d810f78eb9 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -8,9 +8,8 @@ use crate::va_arg::emit_va_arg; use crate::value::Value; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; -use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; -use rustc_codegen_ssa::errors::InvalidMonomorphization; +use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; @@ -835,40 +834,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( llret_ty: &'ll Type, span: Span, ) -> Result<&'ll Value, ()> { - // macros for error handling: - #[allow(unused_macro_rules)] - macro_rules! emit_error { - ($msg: tt) => { - emit_error!($msg, ) - }; - ($msg: tt, $($fmt: tt)*) => { - span_invalid_monomorphization_error( - bx.sess(), span, - &format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg), - name, $($fmt)*)); - } - } - macro_rules! return_error { - ($($fmt: tt)*) => { - { - emit_error!($($fmt)*); - return Err(()); - } - } + ($diag: expr) => {{ + bx.sess().emit_err($diag); + return Err(()); + }}; } macro_rules! require { - ($cond: expr, $($fmt: tt)*) => { + ($cond: expr, $diag: expr) => { if !$cond { - return_error!($($fmt)*); + return_error!($diag); } }; } macro_rules! require_simd { - ($ty: expr, $position: expr) => { - require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) + ($ty: expr, $diag: expr) => { + require!($ty.is_simd(), $diag) }; } @@ -878,7 +861,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let arg_tys = sig.inputs(); if name == sym::simd_select_bitmask { - require_simd!(arg_tys[1], "argument"); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); + let (len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let expected_int_bits = (len.max(8) - 1).next_power_of_two(); @@ -899,12 +886,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let ptr = bx.pointercast(place.llval, bx.cx.type_ptr_to(int_ty)); bx.load(int_ty, ptr, Align::ONE) } - _ => return_error!( - "invalid bitmask `{}`, expected `u{}` or `[u8; {}]`", + _ => return_error!(InvalidMonomorphization::InvalidBitmask { + span, + name, mask_ty, expected_int_bits, expected_bytes - ), + }), }; let i1 = bx.type_i1(); @@ -916,7 +904,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( } // every intrinsic below takes a SIMD vector as its first argument - require_simd!(arg_tys[0], "input"); + require_simd!(arg_tys[0], InvalidMonomorphization::SimdInput { span, name, ty: arg_tys[0] }); let in_ty = arg_tys[0]; let comparison = match name { @@ -931,23 +919,24 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx()); if let Some(cmp_op) = comparison { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); + require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); require!( bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, - "expected return type with integer elements, found `{}` with non-integer `{}`", - ret_ty, - out_ty + InvalidMonomorphization::ReturnIntegerType { span, name, ret_ty, out_ty } ); return Ok(compare_simd_types( @@ -972,10 +961,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span_bug!(span, "could not evaluate shuffle index array length") }) } - _ => return_error!( - "simd_shuffle index must be an array of `u32`, got `{}`", - args[2].layout.ty - ), + _ => return_error!(InvalidMonomorphization::SimdShuffle { + span, + name, + ty: args[2].layout.ty + }), } } else { stripped.parse().unwrap_or_else(|_| { @@ -983,23 +973,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( }) }; - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); require!( out_len == n, - "expected return type of length {}, found `{}` with length {}", - n, - ret_ty, - out_len + InvalidMonomorphization::ReturnLength { span, name, in_len: n, ret_ty, out_len } ); require!( in_elem == out_ty, - "expected return element type `{}` (element of input `{}`), \ - found `{}` with element type `{}`", - in_elem, - in_ty, - ret_ty, - out_ty + InvalidMonomorphization::ReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty } ); let total_len = u128::from(in_len) * 2; @@ -1012,15 +994,20 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let val = bx.const_get_elt(vector, i as u64); match bx.const_to_opt_u128(val, true) { None => { - emit_error!("shuffle index #{} is not a constant", arg_idx); + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexNotConstant { + span, + name, + arg_idx, + }); None } Some(idx) if idx >= total_len => { - emit_error!( - "shuffle index #{} is out of bounds (limit {})", + bx.sess().emit_err(InvalidMonomorphization::ShuffleIndexOutOfBounds { + span, + name, arg_idx, - total_len - ); + total_len, + }); None } Some(idx) => Some(bx.const_i32(idx as i32)), @@ -1041,10 +1028,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_insert { require!( in_elem == arg_tys[2], - "expected inserted type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - arg_tys[2] + InvalidMonomorphization::InsertedType { + span, + name, + in_elem, + in_ty, + out_ty: arg_tys[2] + } ); return Ok(bx.insert_element( args[0].immediate(), @@ -1055,10 +1045,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_extract { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())); } @@ -1066,17 +1053,18 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::simd_select { let m_elem_ty = in_elem; let m_len = in_len; - require_simd!(arg_tys[1], "argument"); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdArgument { span, name, ty: arg_tys[1] } + ); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); require!( m_len == v_len, - "mismatched lengths: mask length `{}` != other vector length `{}`", - m_len, - v_len + InvalidMonomorphization::MismatchedLengths { span, name, m_len, v_len } ); match m_elem_ty.kind() { ty::Int(_) => {} - _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty), + _ => return_error!(InvalidMonomorphization::MaskType { span, name, ty: m_elem_ty }), } // truncate the mask to a vector of i1s let i1 = bx.type_i1(); @@ -1108,11 +1096,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( args[0].immediate(), i.bit_width().unwrap_or_else(|| bx.data_layout().pointer_size.bits()), ), - _ => return_error!( - "vector argument `{}`'s element type `{}`, expected integer element type", + _ => return_error!(InvalidMonomorphization::VectorArgument { + span, + name, in_ty, in_elem - ), + }), }; // Shift the MSB to the right by "in_elem_bitwidth - 1" into the first bit position. @@ -1147,12 +1136,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>( let ptr = bx.pointercast(ptr, bx.cx.type_ptr_to(array_ty)); return Ok(bx.load(array_ty, ptr, Align::ONE)); } - _ => return_error!( - "cannot return `{}`, expected `u{}` or `[u8; {}]`", + _ => return_error!(InvalidMonomorphization::CannotReturn { + span, + name, ret_ty, expected_int_bits, expected_bytes - ), + }), } } @@ -1165,24 +1155,27 @@ fn generic_simd_intrinsic<'ll, 'tcx>( span: Span, args: &[OperandRef<'tcx, &'ll Value>], ) -> Result<&'ll Value, ()> { + macro_rules! return_error { + ($diag: expr) => {{ + bx.sess().emit_err($diag); + return Err(()); + }}; + } + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { let elem_ty = bx.cx.type_float_from_ty(*f); match f.bit_width() { 32 => ("f32", elem_ty), 64 => ("f64", elem_ty), - _ => { - bx.sess().emit_err(InvalidMonomorphization::FloatingPointVector { - span, - name, - f_ty: *f, - in_ty, - }); - return Err(()); - } + _ => return_error!(InvalidMonomorphization::FloatingPointVector { + span, + name, + f_ty: *f, + in_ty, + }), } } else { - bx.sess().emit_err(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); - return Err(()); + return_error!(InvalidMonomorphization::FloatingPointType { span, name, in_ty }); }; let vec_ty = bx.type_vector(elem_ty, in_len); @@ -1204,10 +1197,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), - _ => { - bx.sess().emit_err(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }); - return Err(()); - } + _ => return_error!(InvalidMonomorphization::UnrecognizedIntrinsic { span, name }), }; let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let f = bx.declare_cfn(llvm_name, llvm::UnnamedAddr::No, fn_ty); @@ -1301,37 +1291,48 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); - require_simd!(ret_ty, "return"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); // Of the same length: let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "second", - in_len, - in_ty, - arg_tys[1], - out_len + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len + } ); require!( in_len == out_len2, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "third", - in_len, - in_ty, - arg_tys[2], - out_len2 + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: out_len2 + } ); // The return type must match the first argument type - require!(ret_ty == in_ty, "expected return type `{}`, found `{}`", in_ty, ret_ty); + require!( + ret_ty == in_ty, + InvalidMonomorphization::ExpectedReturnType { span, name, in_ty, ret_ty } + ); // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { @@ -1358,15 +1359,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*_ {}`", - element_ty1, - arg_tys[1], - in_elem, - in_ty, - element_ty1, - in_elem + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Not, + } ); unreachable!(); } @@ -1382,10 +1383,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of third argument `{}` \ - to be a signed integer type", - element_ty2, - arg_tys[2] + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } ); } } @@ -1434,32 +1437,40 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // * M: any integer width is supported, will be truncated to i1 // All types must be simd vector types - require_simd!(in_ty, "first"); - require_simd!(arg_tys[1], "second"); - require_simd!(arg_tys[2], "third"); + require_simd!(in_ty, InvalidMonomorphization::SimdFirst { span, name, ty: in_ty }); + require_simd!( + arg_tys[1], + InvalidMonomorphization::SimdSecond { span, name, ty: arg_tys[1] } + ); + require_simd!( + arg_tys[2], + InvalidMonomorphization::SimdThird { span, name, ty: arg_tys[2] } + ); // Of the same length: let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx()); require!( in_len == element_len1, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "second", - in_len, - in_ty, - arg_tys[1], - element_len1 + InvalidMonomorphization::SecondArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[1], + out_len: element_len1 + } ); require!( in_len == element_len2, - "expected {} argument with length {} (same as input type `{}`), \ - found `{}` with length {}", - "third", - in_len, - in_ty, - arg_tys[2], - element_len2 + InvalidMonomorphization::ThirdArgumentLength { + span, + name, + in_len, + in_ty, + arg_ty: arg_tys[2], + out_len: element_len2 + } ); // This counts how many pointers @@ -1490,15 +1501,15 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of second argument `{}` \ - to be a pointer to the element type `{}` of the first \ - argument `{}`, found `{}` != `*mut {}`", - element_ty1, - arg_tys[1], - in_elem, - in_ty, - element_ty1, - in_elem + InvalidMonomorphization::ExpectedElementType { + span, + name, + expected_element: element_ty1, + second_arg: arg_tys[1], + in_elem, + in_ty, + mutability: ExpectedPointerMutability::Mut, + } ); unreachable!(); } @@ -1513,10 +1524,12 @@ fn generic_simd_intrinsic<'ll, 'tcx>( _ => { require!( false, - "expected element type `{}` of third argument `{}` \ - be a signed integer type", - element_ty2, - arg_tys[2] + InvalidMonomorphization::ThirdArgElementType { + span, + name, + expected_element: element_ty2, + third_arg: arg_tys[2] + } ); } } @@ -1563,10 +1576,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_) | ty::Uint(_) => { @@ -1589,25 +1599,28 @@ fn generic_simd_intrinsic<'ll, 'tcx>( 32 => bx.const_real(bx.type_f32(), $identity), 64 => bx.const_real(bx.type_f64(), $identity), v => return_error!( - r#" -unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, - sym::$name, - in_ty, - in_elem, - v, - ret_ty + InvalidMonomorphization::UnsupportedSymbolOfSize { + span, + name, + symbol: sym::$name, + in_ty, + in_elem, + size: v, + ret_ty + } ), } }; Ok(bx.$float_reduce(acc, args[0].immediate())) } - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1635,22 +1648,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, if name == sym::$name { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); return match in_elem.kind() { ty::Int(_i) => Ok(bx.$int_red(args[0].immediate(), true)), ty::Uint(_u) => Ok(bx.$int_red(args[0].immediate(), false)), ty::Float(_f) => Ok(bx.$float_red(args[0].immediate())), - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1668,22 +1679,20 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let input = if !$boolean { require!( ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, - in_ty, - ret_ty + InvalidMonomorphization::ReturnType { span, name, in_elem, in_ty, ret_ty } ); args[0].immediate() } else { match in_elem.kind() { ty::Int(_) | ty::Uint(_) => {} - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), } // boolean reductions operate on vectors of i1s: @@ -1696,13 +1705,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let r = bx.$red(input); Ok(if !$boolean { r } else { bx.zext(r, bx.type_bool()) }) } - _ => return_error!( - "unsupported {} from `{}` with element `{}` to `{}`", - sym::$name, + _ => return_error!(InvalidMonomorphization::UnsupportedSymbol { + span, + name, + symbol: sym::$name, in_ty, in_elem, ret_ty - ), + }), }; } }; @@ -1715,16 +1725,18 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bitwise_red!(simd_reduce_any: vector_reduce_or, true); if name == sym::simd_cast_ptr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { @@ -1733,9 +1745,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); assert!(!check_sized); // we are in codegen, so we shouldn't see these types - require!(metadata.is_unit(), "cannot cast fat pointer `{}`", in_elem) + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: in_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) } - _ => return_error!("expected pointer, got `{}`", in_elem), } match out_elem.kind() { ty::RawPtr(p) => { @@ -1743,9 +1760,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, bx.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty) }); assert!(!check_sized); // we are in codegen, so we shouldn't see these types - require!(metadata.is_unit(), "cannot cast to fat pointer `{}`", out_elem) + require!( + metadata.is_unit(), + InvalidMonomorphization::CastFatPointer { span, name, ty: out_elem } + ); + } + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) } - _ => return_error!("expected pointer, got `{}`", out_elem), } if in_elem == out_elem { @@ -1756,66 +1778,76 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } if name == sym::simd_expose_addr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { ty::RawPtr(_) => {} - _ => return_error!("expected pointer, got `{}`", in_elem), + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: in_elem }) + } } match out_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} - _ => return_error!("expected `usize`, got `{}`", out_elem), + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: out_elem }), } return Ok(bx.ptrtoint(args[0].immediate(), llret_ty)); } if name == sym::simd_from_exposed_addr { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); match in_elem.kind() { ty::Uint(ty::UintTy::Usize) => {} - _ => return_error!("expected `usize`, got `{}`", in_elem), + _ => return_error!(InvalidMonomorphization::ExpectedUsize { span, name, ty: in_elem }), } match out_elem.kind() { ty::RawPtr(_) => {} - _ => return_error!("expected pointer, got `{}`", out_elem), + _ => { + return_error!(InvalidMonomorphization::ExpectedPointer { span, name, ty: out_elem }) + } } return Ok(bx.inttoptr(args[0].immediate(), llret_ty)); } if name == sym::simd_cast || name == sym::simd_as { - require_simd!(ret_ty, "return"); + require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); require!( in_len == out_len, - "expected return type with length {} (same as input type `{}`), \ - found `{}` with length {}", - in_len, - in_ty, - ret_ty, - out_len + InvalidMonomorphization::ReturnLengthInputType { + span, + name, + in_len, + in_ty, + ret_ty, + out_len + } ); // casting cares about nominal type, not just structural type if in_elem == out_elem { @@ -1894,11 +1926,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, } require!( false, - "unsupported cast from `{}` with element `{}` to `{}` with element `{}`", - in_ty, - in_elem, - ret_ty, - out_elem + InvalidMonomorphization::UnsupportedCast { + span, + name, + in_ty, + in_elem, + ret_ty, + out_elem + } ); } macro_rules! arith_binary { @@ -1910,10 +1945,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + require!( + false, + InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem } + ); })* } } @@ -1941,10 +1976,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, })* _ => {}, } - require!(false, - "unsupported operation on `{}` with element `{}`", - in_ty, - in_elem) + require!( + false, + InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem } + ); })* } } @@ -1982,12 +2017,12 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_int_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits), bx.cx.type_uint_from_ty(i)), _ => { - return_error!( - "expected element type `{}` of vector type `{}` \ - to be a signed or unsigned integer type", - arg_tys[0].simd_size_and_type(bx.tcx()).1, - arg_tys[0] - ); + return_error!(InvalidMonomorphization::ExpectedVectorElementType { + span, + name, + expected_element: arg_tys[0].simd_size_and_type(bx.tcx()).1, + vector_type: arg_tys[0] + }); } }; let llvm_intrinsic = &format!( diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 71f9179d02cca..e1abb73a504a3 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,10 +1,8 @@ #![allow(non_camel_case_types)] -use rustc_errors::struct_span_err; use rustc_hir::LangItem; use rustc_middle::mir::interpret::ConstValue; use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt}; -use rustc_session::Session; use rustc_span::Span; use crate::base; @@ -193,10 +191,6 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } -pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { - struct_span_err!(a, b, E0511, "{}", c).emit(); -} - pub fn asm_const_to_str<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index 852925a1787c8..29876b9542241 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -663,4 +663,326 @@ pub enum InvalidMonomorphization<'tcx> { span: Span, name: Symbol, }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_argument, code = "E0511")] + SimdArgument { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_input, code = "E0511")] + SimdInput { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_first, code = "E0511")] + SimdFirst { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_second, code = "E0511")] + SimdSecond { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_third, code = "E0511")] + SimdThird { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_return, code = "E0511")] + SimdReturn { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_invalid_bitmask, code = "E0511")] + InvalidBitmask { + #[primary_span] + span: Span, + name: Symbol, + mask_ty: Ty<'tcx>, + expected_int_bits: u64, + expected_bytes: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_length_input_type, code = "E0511")] + ReturnLengthInputType { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_second_argument_length, code = "E0511")] + SecondArgumentLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + arg_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_third_argument_length, code = "E0511")] + ThirdArgumentLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + in_ty: Ty<'tcx>, + arg_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_integer_type, code = "E0511")] + ReturnIntegerType { + #[primary_span] + span: Span, + name: Symbol, + ret_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_simd_shuffle, code = "E0511")] + SimdShuffle { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_length, code = "E0511")] + ReturnLength { + #[primary_span] + span: Span, + name: Symbol, + in_len: u64, + ret_ty: Ty<'tcx>, + out_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_element, code = "E0511")] + ReturnElement { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_not_constant, code = "E0511")] + ShuffleIndexNotConstant { + #[primary_span] + span: Span, + name: Symbol, + arg_idx: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds, code = "E0511")] + ShuffleIndexOutOfBounds { + #[primary_span] + span: Span, + name: Symbol, + arg_idx: u64, + total_len: u128, + }, + + #[diag(codegen_ssa_invalid_monomorphization_inserted_type, code = "E0511")] + InsertedType { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + out_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_return_type, code = "E0511")] + ReturnType { + #[primary_span] + span: Span, + name: Symbol, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_return_type, code = "E0511")] + ExpectedReturnType { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_mismatched_lengths, code = "E0511")] + MismatchedLengths { + #[primary_span] + span: Span, + name: Symbol, + m_len: u64, + v_len: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_mask_type, code = "E0511")] + MaskType { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_vector_argument, code = "E0511")] + VectorArgument { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_cannot_return, code = "E0511")] + CannotReturn { + #[primary_span] + span: Span, + name: Symbol, + ret_ty: Ty<'tcx>, + expected_int_bits: u64, + expected_bytes: u64, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_element_type, code = "E0511")] + ExpectedElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + second_arg: Ty<'tcx>, + in_elem: Ty<'tcx>, + in_ty: Ty<'tcx>, + mutability: ExpectedPointerMutability, + }, + + #[diag(codegen_ssa_invalid_monomorphization_third_arg_element_type, code = "E0511")] + ThirdArgElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + third_arg: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size, code = "E0511")] + UnsupportedSymbolOfSize { + #[primary_span] + span: Span, + name: Symbol, + symbol: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + size: u64, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_symbol, code = "E0511")] + UnsupportedSymbol { + #[primary_span] + span: Span, + name: Symbol, + symbol: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + ret_ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_cast_fat_pointer, code = "E0511")] + CastFatPointer { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_pointer, code = "E0511")] + ExpectedPointer { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_usize, code = "E0511")] + ExpectedUsize { + #[primary_span] + span: Span, + name: Symbol, + ty: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_cast, code = "E0511")] + UnsupportedCast { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + ret_ty: Ty<'tcx>, + out_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_unsupported_operation, code = "E0511")] + UnsupportedOperation { + #[primary_span] + span: Span, + name: Symbol, + in_ty: Ty<'tcx>, + in_elem: Ty<'tcx>, + }, + + #[diag(codegen_ssa_invalid_monomorphization_expected_vector_element_type, code = "E0511")] + ExpectedVectorElementType { + #[primary_span] + span: Span, + name: Symbol, + expected_element: Ty<'tcx>, + vector_type: Ty<'tcx>, + }, +} + +pub enum ExpectedPointerMutability { + Mut, + Not, +} + +impl IntoDiagnosticArg for ExpectedPointerMutability { + fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { + match self { + ExpectedPointerMutability::Mut => DiagnosticArgValue::Str(Cow::Borrowed("*mut")), + ExpectedPointerMutability::Not => DiagnosticArgValue::Str(Cow::Borrowed("*_")), + } + } } diff --git a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl index d10c399bb6afc..c59c992afb232 100644 --- a/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl +++ b/compiler/rustc_error_messages/locales/en-US/codegen_ssa.ftl @@ -226,4 +226,70 @@ codegen_ssa_invalid_monomorphization_floating_point_type = invalid monomorphizat codegen_ssa_invalid_monomorphization_unrecognized_intrinsic = invalid monomorphization of `{$name}` intrinsic: unrecognized intrinsic `{$name}` +codegen_ssa_invalid_monomorphization_simd_argument = invalid monomorphization of `{$name}` intrinsic: expected SIMD argument type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_input = invalid monomorphization of `{$name}` intrinsic: expected SIMD input type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_first = invalid monomorphization of `{$name}` intrinsic: expected SIMD first type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_second = invalid monomorphization of `{$name}` intrinsic: expected SIMD second type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_third = invalid monomorphization of `{$name}` intrinsic: expected SIMD third type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_simd_return = invalid monomorphization of `{$name}` intrinsic: expected SIMD return type, found non-SIMD `{$ty}` + +codegen_ssa_invalid_monomorphization_invalid_bitmask = invalid monomorphization of `{$name}` intrinsic: invalid bitmask `{$mask_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + codegen_ssa_polymorphic_constant_too_generic = codegen encountered polymorphic constant: TooGeneric + +codegen_ssa_invalid_monomorphization_return_length_input_type = invalid monomorphization of `{$name}` intrinsic: expected return type with length {$in_len} (same as input type `{$in_ty}`), found `{$ret_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_second_argument_length = invalid monomorphization of `{$name}` intrinsic: expected second argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_third_argument_length = invalid monomorphization of `{$name}` intrinsic: expected third argument with length {$in_len} (same as input type `{$in_ty}`), found `{$arg_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_return_integer_type = invalid monomorphization of `{$name}` intrinsic: expected return type with integer elements, found `{$ret_ty}` with non-integer `{$out_ty}` + +codegen_ssa_invalid_monomorphization_simd_shuffle = invalid monomorphization of `{$name}` intrinsic: simd_shuffle index must be an array of `u32`, got `{$ty}` + +codegen_ssa_invalid_monomorphization_return_length = invalid monomorphization of `{$name}` intrinsic: expected return type of length {$in_len}, found `{$ret_ty}` with length {$out_len} + +codegen_ssa_invalid_monomorphization_return_element = invalid monomorphization of `{$name}` intrinsic: expected return element type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` with element type `{$out_ty}` + +codegen_ssa_invalid_monomorphization_shuffle_index_not_constant = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is not a constant + +codegen_ssa_invalid_monomorphization_shuffle_index_out_of_bounds = invalid monomorphization of `{$name}` intrinsic: shuffle index #{$arg_idx} is out of bounds (limit {$total_len}) + +codegen_ssa_invalid_monomorphization_inserted_type = invalid monomorphization of `{$name}` intrinsic: expected inserted type `{$in_elem}` (element of input `{$in_ty}`), found `{$out_ty}` + +codegen_ssa_invalid_monomorphization_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_elem}` (element of input `{$in_ty}`), found `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_expected_return_type = invalid monomorphization of `{$name}` intrinsic: expected return type `{$in_ty}`, found `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_mismatched_lengths = invalid monomorphization of `{$name}` intrinsic: mismatched lengths: mask length `{$m_len}` != other vector length `{$v_len}` + +codegen_ssa_invalid_monomorphization_mask_type = invalid monomorphization of `{$name}` intrinsic: mask element type is `{$ty}`, expected `i_` + +codegen_ssa_invalid_monomorphization_vector_argument = invalid monomorphization of `{$name}` intrinsic: vector argument `{$in_ty}`'s element type `{$in_elem}`, expected integer element type + +codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]` + +codegen_ssa_invalid_monomorphization_expected_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of second argument `{$second_arg}` to be a pointer to the element type `{$in_elem}` of the first argument `{$in_ty}`, found `{$expected_element}` != `{$mutability} {$in_elem}` + +codegen_ssa_invalid_monomorphization_third_arg_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of third argument `{$third_arg}` to be a signed integer type + +codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` + +codegen_ssa_invalid_monomorphization_cast_fat_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast fat pointer `{$ty}` + +codegen_ssa_invalid_monomorphization_expected_pointer = invalid monomorphization of `{$name}` intrinsic: expected pointer, got `{$ty}` + +codegen_ssa_invalid_monomorphization_expected_usize = invalid monomorphization of `{$name}` intrinsic: expected `usize`, got `{$ty}` + +codegen_ssa_invalid_monomorphization_unsupported_cast = invalid monomorphization of `{$name}` intrinsic: unsupported cast from `{$in_ty}` with element `{$in_elem}` to `{$ret_ty}` with element `{$out_elem}` + +codegen_ssa_invalid_monomorphization_unsupported_operation = invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}` + +codegen_ssa_invalid_monomorphization_expected_vector_element_type = invalid monomorphization of `{$name}` intrinsic: expected element type `{$expected_element}` of vector type `{$vector_type}` to be a signed or unsigned integer type From 4d63d7d91c984342afd5bca0c5cf4cb1761973bf Mon Sep 17 00:00:00 2001 From: Jhonny Bill Mena Date: Sat, 26 Nov 2022 21:12:44 -0500 Subject: [PATCH 12/32] UPDATE - migrate outstanding diagnostic in link.rs --- compiler/rustc_codegen_ssa/src/back/link.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index edde1537b81e1..5324214ac78c1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2612,7 +2612,7 @@ fn add_static_crate<'a>( sess.target.no_builtins || !codegen_results.crate_info.is_no_builtins.contains(&cnum); let mut archive = archive_builder_builder.new_archive_builder(sess); - if let Err(e) = archive.add_archive( + if let Err(error) = archive.add_archive( cratepath, Box::new(move |f| { if f == METADATA_FILENAME { @@ -2652,7 +2652,7 @@ fn add_static_crate<'a>( false }), ) { - sess.fatal(&format!("failed to build archive from rlib: {}", e)); + sess.emit_fatal(errors::RlibArchiveBuildFailure { error }); } if archive.build(&dst) { link_upstream(&dst); From 8360a40a8a2ff2098eed561dd89c577349dbbb76 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 8 Sep 2022 22:28:00 +0300 Subject: [PATCH 13/32] Migrate named_anon_conflict.rs --- .../locales/en-US/infer.ftl | 11 ++++++ compiler/rustc_infer/src/errors/mod.rs | 24 +++++++++++- .../nice_region_error/named_anon_conflict.rs | 38 +++++++------------ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index c9d83746d5454..40ca2c1cd1626 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -172,3 +172,14 @@ infer_msl_unmet_req = because this has an unmet lifetime requirement infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement infer_suggest_add_let_for_letchains = consider adding `let` + +infer_explicit_lifetime_required = explicit lifetime required in {$ident_kind -> + [ident] the type of `{$simple_ident}` + *[param_type] parameter type +} + .label = lifetime `{$named}` required + +infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$ident_kind -> + [ident] the type of `{$simple_ident}` + *[param_type] type +} diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index c4f11472d5548..99112397c7f68 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -357,8 +357,8 @@ impl AddToDiagnostic for LifetimeMismatchLabels { pub struct AddLifetimeParamsSuggestion<'a> { pub tcx: TyCtxt<'a>, pub sub: Region<'a>, - pub ty_sup: &'a Ty<'a>, - pub ty_sub: &'a Ty<'a>, + pub ty_sup: &'a hir::Ty<'a>, + pub ty_sub: &'a hir::Ty<'a>, pub add_note: bool, } @@ -520,3 +520,23 @@ pub struct MismatchedStaticLifetime<'a> { #[subdiagnostic] pub implicit_static_lifetimes: Vec, } + +#[derive(SessionDiagnostic)] +#[diag(infer::explicit_lifetime_required, code = "E0621")] +pub struct ExplicitLifetimeRequired<'a> { + #[primary_span] + #[label] + pub span: Span, + pub ident_kind: &'static str, + pub simple_ident: String, + pub named: String, + + #[suggestion( + infer::explicit_lifetime_required_sugg, + code = "{new_ty}", + applicability = "unspecified" + )] + pub new_ty_span: Span, + #[skip_arg] + pub new_ty: Ty<'a>, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 3fe7c1598fc3f..d7751158902b8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -1,8 +1,11 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where one region is named and the other is anonymous. -use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed}; +use crate::{ + errors::ExplicitLifetimeRequired, + infer::error_reporting::nice_region_error::find_anon_type::find_anon_type, +}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_middle::ty; use rustc_span::symbol::kw; @@ -87,30 +90,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { return None; } - let (error_var, span_label_var) = match param.pat.simple_ident() { - Some(simple_ident) => ( - format!("the type of `{}`", simple_ident), - format!("the type of `{}`", simple_ident), - ), - None => ("parameter type".to_owned(), "type".to_owned()), + let simple_ident = param.pat.simple_ident(); + let (ident_kind, simple_ident) = match simple_ident { + Some(ident) => ("ident", ident.to_string()), + None => ("param_type", String::new()), }; - let mut diag = struct_span_err!( - self.tcx().sess, - span, - E0621, - "explicit lifetime required in {}", - error_var - ); - - diag.span_label(span, format!("lifetime `{}` required", named)); - diag.span_suggestion( - new_ty_span, - &format!("add explicit lifetime `{}` to {}", named, span_label_var), - new_ty, - Applicability::Unspecified, - ); + let named = named.to_string(); - Some(diag) + let err = + ExplicitLifetimeRequired { span, ident_kind, simple_ident, named, new_ty_span, new_ty }; + let err = self.tcx().sess.parse_sess.create_err(err); + Some(err) } } From 2118ff401f64789b6a9e64134d6d2797efee4be9 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 11 Sep 2022 00:45:38 +0300 Subject: [PATCH 14/32] Migrate placeholder_error.rs --- .../locales/en-US/infer.ftl | 28 ++ compiler/rustc_infer/src/errors/mod.rs | 41 +++ .../nice_region_error/placeholder_error.rs | 243 +++++++++--------- 3 files changed, 186 insertions(+), 126 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 40ca2c1cd1626..a52ac1339468c 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -183,3 +183,31 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id [ident] the type of `{$simple_ident}` *[param_type] type } + +infer_actual_impl_expl_1 = {$leading_ellipsis -> + [true] ... + *[false] {""} +}{$kind -> + [signature] closure with signature `{$ty_or_sig}` must implement `{$trait_path}` + [passive] `{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` + *[other] `{$ty_or_sig}` must implement `{$trait_path}` +}{$lt_kind -> + [two] , for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... + [any] , for any lifetime `'{$lifetime_1}`... + [some] , for some specific lifetime `'{lifetime_1}`... + *[nothing] {""} +} + +infer_actual_impl_expl_2 = {$kind_2 -> + [implements_trait] ...but it actually implements `{$trait_path_2}` + [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` + *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` +}{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} + +infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not general enough + .label_satisfy = doesn't satisfy where-clause + .label_where = due to a where-clause on `{$def_id}`... + .label_dup = implementation of `{$trait_def_id}` is not general enough diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 99112397c7f68..f694c5ca40978 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -540,3 +540,44 @@ pub struct ExplicitLifetimeRequired<'a> { #[skip_arg] pub new_ty: Ty<'a>, } + +#[derive(SessionSubdiagnostic)] +pub enum ActualImplExplNotes { + // Field names have to be different across all variants + #[note(infer::actual_impl_expl_1)] + NoteOne { + leading_ellipsis: bool, + kind: &'static str, + ty_or_sig: String, + trait_path: String, + lt_kind: &'static str, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_2)] + NoteTwo { + kind_2: &'static str, + trait_path_2: String, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, +} + +#[derive(SessionDiagnostic)] +#[diag(infer::trait_placeholder_mismatch)] +pub struct TraitPlaceholderMismatch { + #[primary_span] + pub span: Span, + #[label(infer::label_satisfy)] + pub satisfy_span: Option, + #[label(infer::label_where)] + pub where_span: Option, + #[label(infer::label_dup)] + pub dup_span: Option, + pub def_id: String, + pub trait_def_id: String, + + #[subdiagnostic] + pub actual_impl_expl_notes: Vec, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index fed9fda74bfb3..d9fc2ec243f11 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,10 +1,11 @@ +use crate::errors::{ActualImplExplNotes, TraitPlaceholderMismatch}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::intern::Interned; -use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::ExpectedFound; @@ -12,7 +13,7 @@ use rustc_middle::ty::print::{FmtPrinter, Print, RegionHighlightMode}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt}; -use std::fmt::{self, Write}; +use std::fmt; impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and @@ -205,26 +206,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_substs: SubstsRef<'tcx>, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let span = cause.span(); - let msg = format!( - "implementation of `{}` is not general enough", - self.tcx().def_path_str(trait_def_id), - ); - let mut err = self.tcx().sess.struct_span_err(span, &msg); - let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) - | ObligationCauseCode::ExprItemObligation(def_id, ..) = - *cause.code() - { - err.span_label(span, "doesn't satisfy where-clause"); - err.span_label( - self.tcx().def_span(def_id), - &format!("due to a where-clause on `{}`...", self.tcx().def_path_str(def_id)), - ); - true - } else { - err.span_label(span, &msg); - false - }; + let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = + if let ObligationCauseCode::ItemObligation(def_id) + | ObligationCauseCode::ExprItemObligation(def_id, ..) = *cause.code() + { + ( + true, + Some(span), + Some(self.tcx().def_span(def_id)), + None, + self.tcx().def_path_str(def_id), + ) + } else { + (false, None, None, Some(span), String::new()) + }; let expected_trait_ref = self .cx @@ -284,8 +280,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ?expected_self_ty_has_vid, ); - self.explain_actual_impl_that_was_found( - &mut err, + let actual_impl_expl_notes = self.explain_actual_impl_that_was_found( sub_placeholder, sup_placeholder, has_sub, @@ -299,7 +294,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { leading_ellipsis, ); - err + let diag = TraitPlaceholderMismatch { + span, + satisfy_span, + where_span, + dup_span, + def_id, + trait_def_id: self.tcx().def_path_str(trait_def_id), + actual_impl_expl_notes, + }; + + self.tcx().sess.create_err(diag) } /// Add notes with details about the expected and actual trait refs, with attention to cases @@ -309,7 +314,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { /// due to the number of combinations we have to deal with. fn explain_actual_impl_that_was_found( &self, - err: &mut Diagnostic, sub_placeholder: Option>, sup_placeholder: Option>, has_sub: Option, @@ -321,7 +325,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_has_vid: Option, any_self_ty_has_vid: bool, leading_ellipsis: bool, - ) { + ) -> Vec { // HACK(eddyb) maybe move this in a more central location. #[derive(Copy, Clone)] struct Highlighted<'tcx, T> { @@ -380,120 +384,107 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref); expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub); expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup); - err.note(&{ - let passive_voice = match (has_sub, has_sup) { - (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, - (None, None) => { - expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); - match expected_has_vid { - Some(_) => true, - None => any_self_ty_has_vid, - } - } - }; - let mut note = if same_self_type { - let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); - self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); - - if self_ty.value.is_closure() - && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) - { - let closure_sig = self_ty.map(|closure| { - if let ty::Closure(_, substs) = closure.kind() { - self.tcx().signature_unclosure( - substs.as_closure().sig(), - rustc_hir::Unsafety::Normal, - ) - } else { - bug!("type is not longer closure"); - } - }); - - format!( - "{}closure with signature `{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - closure_sig, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - } else { - format!( - "{}`{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - self_ty, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - ) + let passive_voice = match (has_sub, has_sup) { + (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, + (None, None) => { + expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); + match expected_has_vid { + Some(_) => true, + None => any_self_ty_has_vid, } - } else if passive_voice { - format!( - "{}`{}` would have to be implemented for the type `{}`", - if leading_ellipsis { "..." } else { "" }, - expected_trait_ref.map(|tr| tr.print_only_trait_path()), - expected_trait_ref.map(|tr| tr.self_ty()), + } + }; + + let (kind, ty_or_sig, trait_path) = if same_self_type { + let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); + self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); + + if self_ty.value.is_closure() + && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) + { + let closure_sig = self_ty.map(|closure| { + if let ty::Closure(_, substs) = closure.kind() { + self.tcx().signature_unclosure( + substs.as_closure().sig(), + rustc_hir::Unsafety::Normal, + ) + } else { + bug!("type is not longer closure"); + } + }); + ( + "signature", + closure_sig.to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } else { - format!( - "{}`{}` must implement `{}`", - if leading_ellipsis { "..." } else { "" }, - expected_trait_ref.map(|tr| tr.self_ty()), - expected_trait_ref.map(|tr| tr.print_only_trait_path()), + ( + "other", + self_ty.to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) - }; + } + } else if passive_voice { + ( + "passive", + expected_trait_ref.map(|tr| tr.self_ty()).to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + } else { + ( + "other", + expected_trait_ref.map(|tr| tr.self_ty()).to_string(), + expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + ) + }; - match (has_sub, has_sup) { - (Some(n1), Some(n2)) => { - let _ = write!( - note, - ", for any two lifetimes `'{}` and `'{}`...", - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - ); - } - (Some(n), _) | (_, Some(n)) => { - let _ = write!(note, ", for any lifetime `'{}`...", n,); - } - (None, None) => { - if let Some(n) = expected_has_vid { - let _ = write!(note, ", for some specific lifetime `'{}`...", n,); - } + let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) { + (Some(n1), Some(n2)) => ("two", std::cmp::min(n1, n2), std::cmp::max(n1, n2)), + (Some(n), _) | (_, Some(n)) => ("any", n, 0), + (None, None) => { + if let Some(n) = expected_has_vid { + ("some", n, 0) + } else { + ("nothing", 0, 0) } } + }; - note - }); + let note_1 = ActualImplExplNotes::NoteOne { + leading_ellipsis, + kind, + ty_or_sig, + trait_path, + lt_kind, + lifetime_1, + lifetime_2, + }; let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); - err.note(&{ - let passive_voice = match actual_has_vid { - Some(_) => any_self_ty_has_vid, - None => true, - }; - let mut note = if same_self_type { - format!( - "...but it actually implements `{}`", - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - } else if passive_voice { - format!( - "...but `{}` is actually implemented for the type `{}`", - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - actual_trait_ref.map(|tr| tr.self_ty()), - ) - } else { - format!( - "...but `{}` actually implements `{}`", - actual_trait_ref.map(|tr| tr.self_ty()), - actual_trait_ref.map(|tr| tr.print_only_trait_path()), - ) - }; + let passive_voice = match actual_has_vid { + Some(_) => any_self_ty_has_vid, + None => true, + }; - if let Some(n) = actual_has_vid { - let _ = write!(note, ", for some specific lifetime `'{}`", n); - } + let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); + let kind_2 = if same_self_type { + "implements_trait" + } else if passive_voice { + "implemented_for_ty" + } else { + "ty_implements" + }; - note - }); + let has_lifetime = actual_has_vid.is_some(); + let lifetime = actual_has_vid.unwrap_or_default(); + + let note_2 = + ActualImplExplNotes::NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + + vec![note_1, note_2] } } From 3935a81d473167387123f8d48087f5ee446f92c4 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 13 Sep 2022 20:11:42 +0300 Subject: [PATCH 15/32] Migrate trait_impl_difference.rs --- .../locales/en-US/infer.ftl | 10 +++++ compiler/rustc_infer/src/errors/mod.rs | 38 ++++++++++++++++++ .../trait_impl_difference.rs | 40 ++++++------------- 3 files changed, 61 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index a52ac1339468c..d28608cf47de2 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -211,3 +211,13 @@ infer_trait_placeholder_mismatch = implementation of `{$trait_def_id}` is not ge .label_satisfy = doesn't satisfy where-clause .label_where = due to a where-clause on `{$def_id}`... .label_dup = implementation of `{$trait_def_id}` is not general enough + +infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signature + .found = found `{$found}` + .expected = expected `{$expected}` + .expected_found = expected `{$expected}` + {" "}found `{$found}` + +infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output +infer_tid_consider_borriwing = consider borrowing this type parameter in the trait +infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index f694c5ca40978..e2579ab7b7ce0 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -581,3 +581,41 @@ pub struct TraitPlaceholderMismatch { #[subdiagnostic] pub actual_impl_expl_notes: Vec, } + +pub struct ConsiderBorrowingParamHelp { + pub spans: Vec, +} + +impl AddSubdiagnostic for ConsiderBorrowingParamHelp { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut type_param_span: MultiSpan = self.spans.clone().into(); + for &span in &self.spans { + type_param_span.push_span_label(span, fluent::infer::tid_consider_borriwing); + } + diag.span_help(type_param_span, fluent::infer::tid_param_help); + } +} + +#[derive(SessionSubdiagnostic)] +#[help(infer::tid_rel_help)] +pub struct RelationshipHelp; + +#[derive(SessionDiagnostic)] +#[diag(infer::trait_impl_diff)] +pub struct TraitImplDiff { + #[primary_span] + #[label(infer::found)] + pub sp: Span, + #[label(infer::expected)] + pub trait_sp: Span, + #[note(infer::expected_found)] + pub note: (), + #[subdiagnostic] + pub param_help: ConsiderBorrowingParamHelp, + #[subdiagnostic] + // Seems like subdiagnostics are always pushed to the end, so this one + // also has to be a subdiagnostic to maintain order. + pub rel_help: Option, + pub expected: String, + pub found: String, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs index 5d536e982ed02..bacd8894a0fa3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -1,10 +1,11 @@ //! Error Reporting for `impl` items that do not match the obligations from their `trait`. +use crate::errors::{ConsiderBorrowingParamHelp, RelationshipHelp, TraitImplDiff}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::Subtype; use crate::traits::ObligationCauseCode::CompareImplItemObligation; -use rustc_errors::{ErrorGuaranteed, MultiSpan}; +use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; @@ -51,10 +52,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { trait_def_id: DefId, ) -> ErrorGuaranteed { let trait_sp = self.tcx().def_span(trait_def_id); - let mut err = self - .tcx() - .sess - .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature"); // Mark all unnamed regions in the type with a number. // This diagnostic is called in response to lifetime errors, so be informative. @@ -91,9 +88,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let found = self.cx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name; - err.span_label(sp, &format!("found `{}`", found)); - err.span_label(trait_sp, &format!("expected `{}`", expected)); - // Get the span of all the used type parameters in the method. let assoc_item = self.tcx().associated_item(trait_def_id); let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] }; @@ -110,26 +104,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } _ => {} } - let mut type_param_span: MultiSpan = visitor.types.to_vec().into(); - for &span in &visitor.types { - type_param_span - .push_span_label(span, "consider borrowing this type parameter in the trait"); - } - err.note(&format!("expected `{}`\n found `{}`", expected, found)); - - err.span_help( - type_param_span, - "the lifetime requirements from the `impl` do not correspond to the requirements in \ - the `trait`", - ); - if visitor.types.is_empty() { - err.help( - "verify the lifetime relationships in the `trait` and `impl` between the `self` \ - argument, the other inputs and its output", - ); - } - err.emit() + let diag = TraitImplDiff { + sp, + trait_sp, + note: (), + param_help: ConsiderBorrowingParamHelp { spans: visitor.types.to_vec() }, + rel_help: visitor.types.is_empty().then_some(RelationshipHelp), + expected, + found, + }; + + self.tcx().sess.emit_err(diag) } } From 0634b0119cadbf4fcc90d8a399b1c46e1442a5b5 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sat, 17 Sep 2022 02:54:59 +0300 Subject: [PATCH 16/32] Partial work on static_impl_trait.rs --- .../locales/en-US/infer.ftl | 52 +++++ compiler/rustc_infer/src/errors/mod.rs | 97 ++++++++++ .../nice_region_error/static_impl_trait.rs | 183 +++++++----------- 3 files changed, 221 insertions(+), 111 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index d28608cf47de2..7a10f4b7bc549 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -221,3 +221,55 @@ infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signatu infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output infer_tid_consider_borriwing = consider borrowing this type parameter in the trait infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` + +infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement +infer_dtcs_introduces_requirement = calling this method introduces the `impl`'s 'static` requirement +infer_dtcs_has_req_note = the used `impl` has a `'static` requirement +infer_dtcs_suggestion = consider relaxing the implicit `'static` requirement + +infer_but_calling_introduces = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$lifetime_kind -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but calling `{assoc_item}` introduces an implicit `'static` lifetime requirement + .label1 = {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` + } + .label2 = ...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> + [named] `impl` of `{$impl_path}` + *[anon] inherent `impl` + } + +infer_but_needs_to_satisfy = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but it needs to satisfy a `'static` lifetime requirement + .influencer = this data with {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` + }... + .require = {$spans_empty -> + *[true] ...is used and required to live as long as `'static` here + [false] ...and is required to live as long as `'static` here + } + .used_here = ...is used here... + .introduced_by_bound = 'static` lifetime requirement introduced by this bound + +infer_more_targeted = {$has_param_name -> + [true] `{$param_name}` + *[false] `fn` parameter +} has {$has_lifetime -> + [named] lifetime `{lifetime}` + *[anon] an anonymous lifetime `'_` +} but calling `{$ident}` introduces an implicit `'static` lifetime requirement + +infer_ril_introduced_here = `'static` requirement introduced here +infer_ril_introduced_by = requirement introduced by this return type +infer_ril_because_of = because of this returned expression +infer_ril_static_introduced_by = "`'static` lifetime requirement introduced by the return type diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index e2579ab7b7ce0..dc79c725951b3 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -8,6 +8,7 @@ use rustc_hir::{FnRetTy, Ty}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::ty::{Region, TyCtxt}; use rustc_span::symbol::kw; +use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; use crate::infer::error_reporting::{ @@ -619,3 +620,99 @@ pub struct TraitImplDiff { pub expected: String, pub found: String, } + +pub struct DynTraitConstraintSuggestion { + pub span: Span, + pub ident: Ident, +} + +impl AddSubdiagnostic for DynTraitConstraintSuggestion { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + let mut multi_span: MultiSpan = vec![self.span].into(); + multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); + multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); + diag.span_note(multi_span, fluent::infer::dtcs_has_req_note); + diag.span_suggestion_verbose( + self.span.shrink_to_hi(), + fluent::infer::dtcs_suggestion, + " + '_", + Applicability::MaybeIncorrect, + ); + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::but_calling_introduces, code = "E0772")] +pub struct ButCallingIntroduces { + #[label(infer::label1)] + pub param_ty_span: Span, + #[primary_span] + #[label(infer::label2)] + pub cause_span: Span, + + pub has_param_name: bool, + pub param_name: String, + pub has_lifetime: bool, + pub lifetime: String, + pub assoc_item: Symbol, + pub has_impl_path: bool, + pub impl_path: String, +} + +pub struct ReqIntroducedLocations { + pub span: MultiSpan, + pub spans: Vec, + pub fn_decl_span: Span, + pub cause_span: Span, + pub add_label: bool, +} + +impl AddSubdiagnostic for ReqIntroducedLocations { + fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { + for sp in self.spans { + self.span.push_span_label(sp, fluent::infer::ril_introduced_here); + } + + if self.add_label { + self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); + } + self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); + diag.span_note(self.span, fluent::infer::ril_static_introduced_by); + } +} + +pub struct MoreTargeted { + pub ident: Symbol, +} + +impl AddSubdiagnostic for MoreTargeted { + fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + diag.code(rustc_errors::error_code!(E0772)); + diag.set_primary_message(fluent::infer::more_targeted); + diag.set_arg("ident", self.ident); + } +} + +#[derive(SessionDiagnostic)] +#[diag(infer::but_needs_to_satisfy, code = "E0759")] +pub struct ButNeedsToSatisfy { + #[primary_span] + pub sp: Span, + #[label(infer::influencer)] + pub influencer_point: Span, + #[label(infer::used_here)] + pub spans: Vec, + #[label(infer::require)] + pub require_span_as_label: Option, + #[note(infer::require)] + pub require_span_as_note: Option, + #[note(infer::introduced_by_bound)] + pub bound: Option, + + #[subdiagnostic] + pub req_introduces_loc: Option, + + pub spans_empty: bool, + pub has_lifetime: bool, + pub lifetime: String, +} diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index 9bd2202d2601e..b76f7e7689ff9 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -1,11 +1,15 @@ //! Error Reporting for static impl Traits. +use crate::errors::{ + ButCallingIntroduces, ButNeedsToSatisfy, DynTraitConstraintSuggestion, MoreTargeted, + ReqIntroducedLocations, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxIndexSet; -use rustc_errors::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::{AddSubdiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; @@ -49,46 +53,33 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } let param = self.find_param_with_region(*sup_r, *sub_r)?; - let lifetime = if sup_r.has_name() { - format!("lifetime `{}`", sup_r) - } else { - "an anonymous lifetime `'_`".to_string() + let simple_ident = param.param.pat.simple_ident(); + + let (has_impl_path, impl_path) = match ctxt.assoc_item.container { + AssocItemContainer::TraitContainer => { + let id = ctxt.assoc_item.container_id(tcx); + (true, tcx.def_path_str(id)) + } + AssocItemContainer::ImplContainer => (false, String::new()), }; - let mut err = struct_span_err!( - tcx.sess, - cause.span, - E0772, - "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ - requirement", - param - .param - .pat - .simple_ident() - .map(|s| format!("`{}`", s)) - .unwrap_or_else(|| "`fn` parameter".to_string()), - lifetime, - ctxt.assoc_item.name, - ); - err.span_label(param.param_ty_span, &format!("this data with {}...", lifetime)); - err.span_label( - cause.span, - &format!( - "...is used and required to live as long as `'static` here \ - because of an implicit lifetime bound on the {}", - match ctxt.assoc_item.container { - AssocItemContainer::TraitContainer => { - let id = ctxt.assoc_item.container_id(tcx); - format!("`impl` of `{}`", tcx.def_path_str(id)) - } - AssocItemContainer::ImplContainer => "inherent `impl`".to_string(), - }, - ), - ); + + let diag = ButCallingIntroduces { + param_ty_span: param.param_ty_span, + cause_span: cause.span, + has_param_name: simple_ident.is_some(), + param_name: simple_ident.map(|x| x.to_string()).unwrap_or_default(), + has_lifetime: sup_r.has_name(), + lifetime: sup_r.to_string(), + assoc_item: ctxt.assoc_item.name, + has_impl_path, + impl_path, + }; + let mut err = self.tcx().sess.create_err(diag); if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { let reported = err.emit(); return Some(reported); } else { - err.cancel(); + err.cancel() } } return None; @@ -104,25 +95,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let sp = var_origin.span(); let return_sp = sub_origin.span(); let param = self.find_param_with_region(*sup_r, *sub_r)?; - let (lifetime_name, lifetime) = if sup_r.has_name() { - (sup_r.to_string(), format!("lifetime `{}`", sup_r)) - } else { - ("'_".to_owned(), "an anonymous lifetime `'_`".to_string()) - }; - let param_name = param - .param - .pat - .simple_ident() - .map(|s| format!("`{}`", s)) - .unwrap_or_else(|| "`fn` parameter".to_string()); - let mut err = struct_span_err!( - tcx.sess, - sp, - E0759, - "{} has {} but it needs to satisfy a `'static` lifetime requirement", - param_name, - lifetime, - ); + let lifetime_name = if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() }; let (mention_influencer, influencer_point) = if sup_origin.span().overlaps(param.param_ty_span) { @@ -141,7 +114,6 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } else { (!sup_origin.span().overlaps(return_sp), param.param_ty_span) }; - err.span_label(influencer_point, &format!("this data with {}...", lifetime)); debug!("try_report_static_impl_trait: param_info={:?}", param); @@ -155,31 +127,19 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { spans.dedup_by_key(|span| (span.lo(), span.hi())); // We try to make the output have fewer overlapping spans if possible. - let require_msg = if spans.is_empty() { - "...is used and required to live as long as `'static` here" - } else { - "...and is required to live as long as `'static` here" - }; let require_span = if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp }; - for span in &spans { - err.span_label(*span, "...is used here..."); - } - - if spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp) { - // If any of the "captured here" labels appears on the same line or after - // `require_span`, we put it on a note to ensure the text flows by appearing - // always at the end. - err.span_note(require_span, require_msg); + let spans_empty = spans.is_empty(); + let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp); + let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { + Some(*bound) } else { - // We don't need a note, it's already at the end, it can be shown as a `span_label`. - err.span_label(require_span, require_msg); - } + None + }; + + let mut subdiag = None; - if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { - err.span_note(*bound, "`'static` lifetime requirement introduced by this bound"); - } if let SubregionOrigin::Subtype(box TypeTrace { cause, .. }) = sub_origin { if let ObligationCauseCode::ReturnValue(hir_id) | ObligationCauseCode::BlockTailExpression(hir_id) = cause.code() @@ -187,33 +147,50 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let parent_id = tcx.hir().get_parent_item(*hir_id); if let Some(fn_decl) = tcx.hir().fn_decl_by_hir_id(parent_id.into()) { let mut span: MultiSpan = fn_decl.output.span().into(); + let mut spans = Vec::new(); let mut add_label = true; if let hir::FnRetTy::Return(ty) = fn_decl.output { let mut v = StaticLifetimeVisitor(vec![], tcx.hir()); v.visit_ty(ty); if !v.0.is_empty() { span = v.0.clone().into(); - for sp in v.0 { - span.push_span_label(sp, "`'static` requirement introduced here"); - } + spans = v.0; add_label = false; } } - if add_label { - span.push_span_label( - fn_decl.output.span(), - "requirement introduced by this return type", - ); - } - span.push_span_label(cause.span, "because of this returned expression"); - err.span_note( + let fn_decl_span = fn_decl.output.span(); + + subdiag = Some(ReqIntroducedLocations { span, - "`'static` lifetime requirement introduced by the return type", - ); + spans, + fn_decl_span, + cause_span: cause.span, + add_label, + }); } } } + let diag = ButNeedsToSatisfy { + sp, + influencer_point, + spans: spans.clone(), + // If any of the "captured here" labels appears on the same line or after + // `require_span`, we put it on a note to ensure the text flows by appearing + // always at the end. + require_span_as_note: require_as_note.then_some(require_span), + // We don't need a note, it's already at the end, it can be shown as a `span_label`. + require_span_as_label: (!require_as_note).then_some(require_span), + req_introduces_loc: subdiag, + + has_lifetime: sup_r.has_name(), + lifetime: sup_r.to_string(), + spans_empty, + bound, + }; + + let mut err = self.tcx().sess.create_err(diag); + let fn_returns = tcx.return_type_impl_or_dyn_traits(anon_reg_sup.def_id); let mut override_error_code = None; @@ -247,12 +224,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { } if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) { // Provide a more targeted error code and description. - err.code(rustc_errors::error_code!(E0772)); - err.set_primary_message(&format!( - "{} has {} but calling `{}` introduces an implicit `'static` lifetime \ - requirement", - param_name, lifetime, ident, - )); + let retarget_subdiag = MoreTargeted { ident }; + retarget_subdiag.add_to_diagnostic(&mut err); } let arg = match param.param.pat.simple_ident() { @@ -513,21 +486,9 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let mut traits = vec![]; let mut hir_v = HirTraitObjectVisitor(&mut traits, *found_did); hir_v.visit_ty(&self_ty); - for span in &traits { - let mut multi_span: MultiSpan = vec![*span].into(); - multi_span - .push_span_label(*span, "this has an implicit `'static` lifetime requirement"); - multi_span.push_span_label( - ident.span, - "calling this method introduces the `impl`'s 'static` requirement", - ); - err.span_note(multi_span, "the used `impl` has a `'static` requirement"); - err.span_suggestion_verbose( - span.shrink_to_hi(), - "consider relaxing the implicit `'static` requirement", - " + '_", - Applicability::MaybeIncorrect, - ); + for &span in &traits { + let subdiag = DynTraitConstraintSuggestion { span, ident }; + subdiag.add_to_diagnostic(err); suggested = true; } } From 57fdd196aeda1e0fa5829248bd4afb8e6f06d7e5 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 22 Sep 2022 17:29:21 +0300 Subject: [PATCH 17/32] Rebase and fix --- compiler/rustc_infer/src/errors/mod.rs | 26 +++++++++---------- .../nice_region_error/static_impl_trait.rs | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index dc79c725951b3..55df63075d22f 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -4,9 +4,9 @@ use rustc_errors::{ MultiSpan, SubdiagnosticMessage, }; use rustc_hir as hir; -use rustc_hir::{FnRetTy, Ty}; +use rustc_hir::FnRetTy; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{Region, TyCtxt}; +use rustc_middle::ty::{Region, Ty, TyCtxt}; use rustc_span::symbol::kw; use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; @@ -522,7 +522,7 @@ pub struct MismatchedStaticLifetime<'a> { pub implicit_static_lifetimes: Vec, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::explicit_lifetime_required, code = "E0621")] pub struct ExplicitLifetimeRequired<'a> { #[primary_span] @@ -542,7 +542,7 @@ pub struct ExplicitLifetimeRequired<'a> { pub new_ty: Ty<'a>, } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] pub enum ActualImplExplNotes { // Field names have to be different across all variants #[note(infer::actual_impl_expl_1)] @@ -565,7 +565,7 @@ pub enum ActualImplExplNotes { }, } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::trait_placeholder_mismatch)] pub struct TraitPlaceholderMismatch { #[primary_span] @@ -587,7 +587,7 @@ pub struct ConsiderBorrowingParamHelp { pub spans: Vec, } -impl AddSubdiagnostic for ConsiderBorrowingParamHelp { +impl AddToDiagnostic for ConsiderBorrowingParamHelp { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { @@ -597,11 +597,11 @@ impl AddSubdiagnostic for ConsiderBorrowingParamHelp { } } -#[derive(SessionSubdiagnostic)] +#[derive(Subdiagnostic)] #[help(infer::tid_rel_help)] pub struct RelationshipHelp; -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::trait_impl_diff)] pub struct TraitImplDiff { #[primary_span] @@ -626,7 +626,7 @@ pub struct DynTraitConstraintSuggestion { pub ident: Ident, } -impl AddSubdiagnostic for DynTraitConstraintSuggestion { +impl AddToDiagnostic for DynTraitConstraintSuggestion { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); @@ -641,7 +641,7 @@ impl AddSubdiagnostic for DynTraitConstraintSuggestion { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::but_calling_introduces, code = "E0772")] pub struct ButCallingIntroduces { #[label(infer::label1)] @@ -667,7 +667,7 @@ pub struct ReqIntroducedLocations { pub add_label: bool, } -impl AddSubdiagnostic for ReqIntroducedLocations { +impl AddToDiagnostic for ReqIntroducedLocations { fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer::ril_introduced_here); @@ -685,7 +685,7 @@ pub struct MoreTargeted { pub ident: Symbol, } -impl AddSubdiagnostic for MoreTargeted { +impl AddToDiagnostic for MoreTargeted { fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { diag.code(rustc_errors::error_code!(E0772)); diag.set_primary_message(fluent::infer::more_targeted); @@ -693,7 +693,7 @@ impl AddSubdiagnostic for MoreTargeted { } } -#[derive(SessionDiagnostic)] +#[derive(Diagnostic)] #[diag(infer::but_needs_to_satisfy, code = "E0759")] pub struct ButNeedsToSatisfy { #[primary_span] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index b76f7e7689ff9..fbc71bd7e0196 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -9,7 +9,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{AddSubdiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; +use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; use rustc_hir::{self as hir, GenericBound, Item, ItemKind, Lifetime, LifetimeName, Node, TyKind}; From 6c19c08140b7c0c5a9f9f9a434036b460167c87d Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sun, 25 Sep 2022 10:55:42 +0300 Subject: [PATCH 18/32] More descriptive names for ActualImplExplNotes variants --- compiler/rustc_error_messages/locales/en-US/infer.ftl | 4 ++-- compiler/rustc_infer/src/errors/mod.rs | 8 ++++---- .../nice_region_error/placeholder_error.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 7a10f4b7bc549..8cfd20c6eda24 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -184,7 +184,7 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id *[param_type] type } -infer_actual_impl_expl_1 = {$leading_ellipsis -> +infer_actual_impl_expl_expected = {$leading_ellipsis -> [true] ... *[false] {""} }{$kind -> @@ -198,7 +198,7 @@ infer_actual_impl_expl_1 = {$leading_ellipsis -> *[nothing] {""} } -infer_actual_impl_expl_2 = {$kind_2 -> +infer_actual_impl_expl_but_actually = {$kind_2 -> [implements_trait] ...but it actually implements `{$trait_path_2}` [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 55df63075d22f..edd9eca24cb99 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -545,8 +545,8 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { // Field names have to be different across all variants - #[note(infer::actual_impl_expl_1)] - NoteOne { + #[note(infer::actual_impl_expl_expected)] + Expected { leading_ellipsis: bool, kind: &'static str, ty_or_sig: String, @@ -555,8 +555,8 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_2)] - NoteTwo { + #[note(infer::actual_impl_expl_but_actually)] + ButActually { kind_2: &'static str, trait_path_2: String, has_lifetime: bool, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d9fc2ec243f11..cf1032f70063f 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -451,7 +451,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } }; - let note_1 = ActualImplExplNotes::NoteOne { + let note_1 = ActualImplExplNotes::Expected { leading_ellipsis, kind, ty_or_sig, @@ -483,7 +483,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = - ActualImplExplNotes::NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + ActualImplExplNotes::ButActually { kind_2, trait_path_2, ty, has_lifetime, lifetime }; vec![note_1, note_2] } From 71d24da665c122fe885d0f62917c01b7f8e8d77f Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 29 Sep 2022 17:10:43 +0300 Subject: [PATCH 19/32] Split into several messages --- .../locales/en-US/infer.ftl | 71 ++++++-- compiler/rustc_infer/src/errors/mod.rs | 168 +++++++++++++++++- .../nice_region_error/placeholder_error.rs | 58 +++--- 3 files changed, 250 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 8cfd20c6eda24..4a43d150968f8 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -184,25 +184,64 @@ infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$id *[param_type] type } -infer_actual_impl_expl_expected = {$leading_ellipsis -> +infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> [true] ... *[false] {""} -}{$kind -> - [signature] closure with signature `{$ty_or_sig}` must implement `{$trait_path}` - [passive] `{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` - *[other] `{$ty_or_sig}` must implement `{$trait_path}` -}{$lt_kind -> - [two] , for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... - [any] , for any lifetime `'{$lifetime_1}`... - [some] , for some specific lifetime `'{lifetime_1}`... - *[nothing] {""} -} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_signature_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_signature_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_signature_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}closure with signature `{$ty_or_sig}` must implement `{$trait_path}` +infer_actual_impl_expl_expected_passive_two = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_passive_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_passive_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_passive_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}` +infer_actual_impl_expl_expected_other_two = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`... +infer_actual_impl_expl_expected_other_any = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`... +infer_actual_impl_expl_expected_other_some = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{lifetime_1}`... +infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> + [true] ... + *[false] {""} +}`{$ty_or_sig}` must implement `{$trait_path}` -infer_actual_impl_expl_but_actually = {$kind_2 -> - [implements_trait] ...but it actually implements `{$trait_path_2}` - [implemented_for_ty] ...but `{$trait_path_2}` is actually implemented for the type `{$ty}` - *[ty_implements] ...but `{$ty}` actually implements `{$trait_path_2}` -}{$has_lifetime -> +infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path_2}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} +infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path_2}` is actually implemented for the type `{$ty}`{$has_lifetime -> + [true] , for some specific lifetime `'{$lifetime}` + *[false] {""} +} +infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path_2}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index edd9eca24cb99..69fc3be2bc3a7 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -544,20 +544,90 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - // Field names have to be different across all variants - #[note(infer::actual_impl_expl_expected)] - Expected { + // Field names have to be different across Expected* and ButActually variants + #[note(infer::actual_impl_expl_expected_signature_two)] + ExpectedSignatureTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_any)] + ExpectedSignatureAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_some)] + ExpectedSignatureSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_nothing)] + ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_passive_two)] + ExpectedPassiveTwo { leading_ellipsis: bool, - kind: &'static str, ty_or_sig: String, trait_path: String, - lt_kind: &'static str, lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_but_actually)] - ButActually { - kind_2: &'static str, + #[note(infer::actual_impl_expl_expected_passive_any)] + ExpectedPassiveAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_some)] + ExpectedPassiveSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_nothing)] + ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_other_two)] + ExpectedOtherTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_other_any)] + ExpectedOtherAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_some)] + ExpectedOtherSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_nothing)] + ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_but_actually_implements_trait)] + ButActuallyImplementsTrait { trait_path_2: String, has_lifetime: bool, lifetime: usize }, + #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] + ButActuallyImplementedForTy { + trait_path_2: String, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, + #[note(infer::actual_impl_expl_but_actually_ty_implements)] + ButActuallyTyImplements { trait_path_2: String, has_lifetime: bool, lifetime: usize, @@ -565,6 +635,88 @@ pub enum ActualImplExplNotes { }, } +pub enum ActualImplExpectedKind { + Signature, + Passive, + Other, +} + +pub enum ActualImplExpectedLifetimeKind { + Two, + Any, + Some, + Nothing, +} + +impl ActualImplExplNotes { + pub fn new_expected( + kind: ActualImplExpectedKind, + lt_kind: ActualImplExpectedLifetimeKind, + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + ) -> Self { + match (kind, lt_kind) { + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedSignatureTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedPassiveTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedOtherTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path } + } + } + } +} + #[derive(Diagnostic)] #[diag(infer::trait_placeholder_mismatch)] pub struct TraitPlaceholderMismatch { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index cf1032f70063f..d2fd4f6cd7cab 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,4 +1,7 @@ -use crate::errors::{ActualImplExplNotes, TraitPlaceholderMismatch}; +use crate::errors::{ + ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, + TraitPlaceholderMismatch, +}; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; @@ -414,52 +417,54 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } }); ( - "signature", + ActualImplExpectedKind::Signature, closure_sig.to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } else { ( - "other", + ActualImplExpectedKind::Other, self_ty.to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } } else if passive_voice { ( - "passive", + ActualImplExpectedKind::Passive, expected_trait_ref.map(|tr| tr.self_ty()).to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) } else { ( - "other", + ActualImplExpectedKind::Other, expected_trait_ref.map(|tr| tr.self_ty()).to_string(), expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), ) }; let (lt_kind, lifetime_1, lifetime_2) = match (has_sub, has_sup) { - (Some(n1), Some(n2)) => ("two", std::cmp::min(n1, n2), std::cmp::max(n1, n2)), - (Some(n), _) | (_, Some(n)) => ("any", n, 0), + (Some(n1), Some(n2)) => { + (ActualImplExpectedLifetimeKind::Two, std::cmp::min(n1, n2), std::cmp::max(n1, n2)) + } + (Some(n), _) | (_, Some(n)) => (ActualImplExpectedLifetimeKind::Any, n, 0), (None, None) => { if let Some(n) = expected_has_vid { - ("some", n, 0) + (ActualImplExpectedLifetimeKind::Some, n, 0) } else { - ("nothing", 0, 0) + (ActualImplExpectedLifetimeKind::Nothing, 0, 0) } } }; - let note_1 = ActualImplExplNotes::Expected { - leading_ellipsis, + let note_1 = ActualImplExplNotes::new_expected( kind, + lt_kind, + leading_ellipsis, ty_or_sig, trait_path, - lt_kind, lifetime_1, lifetime_2, - }; + ); let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); @@ -471,19 +476,26 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); - let kind_2 = if same_self_type { - "implements_trait" - } else if passive_voice { - "implemented_for_ty" - } else { - "ty_implements" - }; - let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); - let note_2 = - ActualImplExplNotes::ButActually { kind_2, trait_path_2, ty, has_lifetime, lifetime }; + let note_2 = if same_self_type { + ActualImplExplNotes::ButActuallyImplementsTrait { trait_path_2, has_lifetime, lifetime } + } else if passive_voice { + ActualImplExplNotes::ButActuallyImplementedForTy { + trait_path_2, + ty, + has_lifetime, + lifetime, + } + } else { + ActualImplExplNotes::ButActuallyTyImplements { + trait_path_2, + ty, + has_lifetime, + lifetime, + } + }; vec![note_1, note_2] } From eb7ce1703bb719c1d038be6572a349a3e70f7ca2 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Fri, 14 Oct 2022 21:50:06 +0300 Subject: [PATCH 20/32] Use eager translation --- .../locales/en-US/infer.ftl | 2 +- compiler/rustc_infer/src/errors/mod.rs | 38 +++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 4a43d150968f8..4219964a87739 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -258,7 +258,7 @@ infer_trait_impl_diff = `impl` item signature doesn't match `trait` item signatu {" "}found `{$found}` infer_tid_rel_help = verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output -infer_tid_consider_borriwing = consider borrowing this type parameter in the trait +infer_tid_consider_borrowing = consider borrowing this type parameter in the trait infer_tid_param_help = the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` infer_dtcs_has_lifetime_req_label = this has an implicit `'static` lifetime requirement diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 69fc3be2bc3a7..9092874dfae78 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -544,7 +544,6 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - // Field names have to be different across Expected* and ButActually variants #[note(infer::actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, @@ -731,7 +730,7 @@ pub struct TraitPlaceholderMismatch { pub def_id: String, pub trait_def_id: String, - #[subdiagnostic] + #[subdiagnostic(eager)] pub actual_impl_expl_notes: Vec, } @@ -740,12 +739,17 @@ pub struct ConsiderBorrowingParamHelp { } impl AddToDiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { - type_param_span.push_span_label(span, fluent::infer::tid_consider_borriwing); + // Seems like we can't call f() here as Into is required + type_param_span.push_span_label(span, fluent::infer::tid_consider_borrowing); } - diag.span_help(type_param_span, fluent::infer::tid_param_help); + let msg = f(diag, fluent::infer::tid_param_help.into()); + diag.span_help(type_param_span, msg); } } @@ -779,14 +783,19 @@ pub struct DynTraitConstraintSuggestion { } impl AddToDiagnostic for DynTraitConstraintSuggestion { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); - diag.span_note(multi_span, fluent::infer::dtcs_has_req_note); + let msg = f(diag, fluent::infer::dtcs_has_req_note.into()); + diag.span_note(multi_span, msg); + let msg = f(diag, fluent::infer::dtcs_suggestion.into()); diag.span_suggestion_verbose( self.span.shrink_to_hi(), - fluent::infer::dtcs_suggestion, + msg, " + '_", Applicability::MaybeIncorrect, ); @@ -820,7 +829,10 @@ pub struct ReqIntroducedLocations { } impl AddToDiagnostic for ReqIntroducedLocations { - fn add_to_diagnostic(mut self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(mut self, diag: &mut Diagnostic, f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { for sp in self.spans { self.span.push_span_label(sp, fluent::infer::ril_introduced_here); } @@ -829,7 +841,8 @@ impl AddToDiagnostic for ReqIntroducedLocations { self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); } self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); - diag.span_note(self.span, fluent::infer::ril_static_introduced_by); + let msg = f(diag, fluent::infer::ril_static_introduced_by.into()); + diag.span_note(self.span, msg); } } @@ -838,7 +851,10 @@ pub struct MoreTargeted { } impl AddToDiagnostic for MoreTargeted { - fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) { + fn add_to_diagnostic_with(self, diag: &mut Diagnostic, _f: F) + where + F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, + { diag.code(rustc_errors::error_code!(E0772)); diag.set_primary_message(fluent::infer::more_targeted); diag.set_arg("ident", self.ident); From 40b221814ea00a9d279474188d81b9a063eb3f68 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Sat, 15 Oct 2022 13:16:51 +0300 Subject: [PATCH 21/32] Rename subdiagnostic fields that do not need to be unique now --- .../rustc_error_messages/locales/en-US/infer.ftl | 6 +++--- compiler/rustc_infer/src/errors/mod.rs | 11 +++-------- .../nice_region_error/placeholder_error.rs | 13 ++++--------- 3 files changed, 10 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 4219964a87739..f74af62702e99 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -233,15 +233,15 @@ infer_actual_impl_expl_expected_other_nothing = {$leading_ellipsis -> *[false] {""} }`{$ty_or_sig}` must implement `{$trait_path}` -infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path_2}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_implements_trait = ...but it actually implements `{$trait_path}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } -infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path_2}` is actually implemented for the type `{$ty}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_implemented_for_ty = ...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } -infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path_2}`{$has_lifetime -> +infer_actual_impl_expl_but_actually_ty_implements = ...but `{$ty}` actually implements `{$trait_path}`{$has_lifetime -> [true] , for some specific lifetime `'{$lifetime}` *[false] {""} } diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 9092874dfae78..1733b6e148fd2 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -617,21 +617,16 @@ pub enum ActualImplExplNotes { #[note(infer::actual_impl_expl_expected_other_nothing)] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, #[note(infer::actual_impl_expl_but_actually_implements_trait)] - ButActuallyImplementsTrait { trait_path_2: String, has_lifetime: bool, lifetime: usize }, + ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { - trait_path_2: String, + trait_path: String, has_lifetime: bool, lifetime: usize, ty: String, }, #[note(infer::actual_impl_expl_but_actually_ty_implements)] - ButActuallyTyImplements { - trait_path_2: String, - has_lifetime: bool, - lifetime: usize, - ty: String, - }, + ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, } pub enum ActualImplExpectedKind { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index d2fd4f6cd7cab..904723c4da9d7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -474,27 +474,22 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { None => true, }; - let trait_path_2 = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = if same_self_type { - ActualImplExplNotes::ButActuallyImplementsTrait { trait_path_2, has_lifetime, lifetime } + ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime } } else if passive_voice { ActualImplExplNotes::ButActuallyImplementedForTy { - trait_path_2, + trait_path, ty, has_lifetime, lifetime, } } else { - ActualImplExplNotes::ButActuallyTyImplements { - trait_path_2, - ty, - has_lifetime, - lifetime, - } + ActualImplExplNotes::ButActuallyTyImplements { trait_path, ty, has_lifetime, lifetime } }; vec![note_1, note_2] From 19b8579803979dd3b1e83f7aa9655920eef14b98 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Mon, 24 Oct 2022 19:06:45 +0300 Subject: [PATCH 22/32] Address changes of pr 103345 --- compiler/rustc_infer/src/errors/mod.rs | 92 +++++++++++++------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 1733b6e148fd2..51b04eb0df011 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -523,7 +523,7 @@ pub struct MismatchedStaticLifetime<'a> { } #[derive(Diagnostic)] -#[diag(infer::explicit_lifetime_required, code = "E0621")] +#[diag(infer_explicit_lifetime_required, code = "E0621")] pub struct ExplicitLifetimeRequired<'a> { #[primary_span] #[label] @@ -533,7 +533,7 @@ pub struct ExplicitLifetimeRequired<'a> { pub named: String, #[suggestion( - infer::explicit_lifetime_required_sugg, + infer_explicit_lifetime_required_sugg, code = "{new_ty}", applicability = "unspecified" )] @@ -544,7 +544,7 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - #[note(infer::actual_impl_expl_expected_signature_two)] + #[note(infer_actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -552,23 +552,23 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_signature_any)] + #[note(infer_actual_impl_expl_expected_signature_any)] ExpectedSignatureAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_signature_some)] + #[note(infer_actual_impl_expl_expected_signature_some)] ExpectedSignatureSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_signature_nothing)] + #[note(infer_actual_impl_expl_expected_signature_nothing)] ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_expected_passive_two)] + #[note(infer_actual_impl_expl_expected_passive_two)] ExpectedPassiveTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -576,23 +576,23 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_passive_any)] + #[note(infer_actual_impl_expl_expected_passive_any)] ExpectedPassiveAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_passive_some)] + #[note(infer_actual_impl_expl_expected_passive_some)] ExpectedPassiveSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_passive_nothing)] + #[note(infer_actual_impl_expl_expected_passive_nothing)] ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_expected_other_two)] + #[note(infer_actual_impl_expl_expected_other_two)] ExpectedOtherTwo { leading_ellipsis: bool, ty_or_sig: String, @@ -600,32 +600,32 @@ pub enum ActualImplExplNotes { lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_expected_other_any)] + #[note(infer_actual_impl_expl_expected_other_any)] ExpectedOtherAny { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_other_some)] + #[note(infer_actual_impl_expl_expected_other_some)] ExpectedOtherSome { leading_ellipsis: bool, ty_or_sig: String, trait_path: String, lifetime_1: usize, }, - #[note(infer::actual_impl_expl_expected_other_nothing)] + #[note(infer_actual_impl_expl_expected_other_nothing)] ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, - #[note(infer::actual_impl_expl_but_actually_implements_trait)] + #[note(infer_actual_impl_expl_but_actually_implements_trait)] ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, - #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] + #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String, }, - #[note(infer::actual_impl_expl_but_actually_ty_implements)] + #[note(infer_actual_impl_expl_but_actually_ty_implements)] ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, } @@ -712,15 +712,15 @@ impl ActualImplExplNotes { } #[derive(Diagnostic)] -#[diag(infer::trait_placeholder_mismatch)] +#[diag(infer_trait_placeholder_mismatch)] pub struct TraitPlaceholderMismatch { #[primary_span] pub span: Span, - #[label(infer::label_satisfy)] + #[label(label_satisfy)] pub satisfy_span: Option, - #[label(infer::label_where)] + #[label(label_where)] pub where_span: Option, - #[label(infer::label_dup)] + #[label(label_dup)] pub dup_span: Option, pub def_id: String, pub trait_def_id: String, @@ -741,26 +741,26 @@ impl AddToDiagnostic for ConsiderBorrowingParamHelp { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required - type_param_span.push_span_label(span, fluent::infer::tid_consider_borrowing); + type_param_span.push_span_label(span, fluent::infer_tid_consider_borrowing); } - let msg = f(diag, fluent::infer::tid_param_help.into()); + let msg = f(diag, fluent::infer_tid_param_help.into()); diag.span_help(type_param_span, msg); } } #[derive(Subdiagnostic)] -#[help(infer::tid_rel_help)] +#[help(infer_tid_rel_help)] pub struct RelationshipHelp; #[derive(Diagnostic)] -#[diag(infer::trait_impl_diff)] +#[diag(infer_trait_impl_diff)] pub struct TraitImplDiff { #[primary_span] - #[label(infer::found)] + #[label(found)] pub sp: Span, - #[label(infer::expected)] + #[label(expected)] pub trait_sp: Span, - #[note(infer::expected_found)] + #[note(expected_found)] pub note: (), #[subdiagnostic] pub param_help: ConsiderBorrowingParamHelp, @@ -783,11 +783,11 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { let mut multi_span: MultiSpan = vec![self.span].into(); - multi_span.push_span_label(self.span, fluent::infer::dtcs_has_lifetime_req_label); - multi_span.push_span_label(self.ident.span, fluent::infer::dtcs_introduces_requirement); - let msg = f(diag, fluent::infer::dtcs_has_req_note.into()); + multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); + multi_span.push_span_label(self.ident.span, fluent::infer_dtcs_introduces_requirement); + let msg = f(diag, fluent::infer_dtcs_has_req_note.into()); diag.span_note(multi_span, msg); - let msg = f(diag, fluent::infer::dtcs_suggestion.into()); + let msg = f(diag, fluent::infer_dtcs_suggestion.into()); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -798,12 +798,12 @@ impl AddToDiagnostic for DynTraitConstraintSuggestion { } #[derive(Diagnostic)] -#[diag(infer::but_calling_introduces, code = "E0772")] +#[diag(infer_but_calling_introduces, code = "E0772")] pub struct ButCallingIntroduces { - #[label(infer::label1)] + #[label(label1)] pub param_ty_span: Span, #[primary_span] - #[label(infer::label2)] + #[label(label2)] pub cause_span: Span, pub has_param_name: bool, @@ -829,14 +829,14 @@ impl AddToDiagnostic for ReqIntroducedLocations { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { for sp in self.spans { - self.span.push_span_label(sp, fluent::infer::ril_introduced_here); + self.span.push_span_label(sp, fluent::infer_ril_introduced_here); } if self.add_label { - self.span.push_span_label(self.fn_decl_span, fluent::infer::ril_introduced_by); + self.span.push_span_label(self.fn_decl_span, fluent::infer_ril_introduced_by); } - self.span.push_span_label(self.cause_span, fluent::infer::ril_because_of); - let msg = f(diag, fluent::infer::ril_static_introduced_by.into()); + self.span.push_span_label(self.cause_span, fluent::infer_ril_because_of); + let msg = f(diag, fluent::infer_ril_static_introduced_by.into()); diag.span_note(self.span, msg); } } @@ -851,25 +851,25 @@ impl AddToDiagnostic for MoreTargeted { F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage, { diag.code(rustc_errors::error_code!(E0772)); - diag.set_primary_message(fluent::infer::more_targeted); + diag.set_primary_message(fluent::infer_more_targeted); diag.set_arg("ident", self.ident); } } #[derive(Diagnostic)] -#[diag(infer::but_needs_to_satisfy, code = "E0759")] +#[diag(infer_but_needs_to_satisfy, code = "E0759")] pub struct ButNeedsToSatisfy { #[primary_span] pub sp: Span, - #[label(infer::influencer)] + #[label(influencer)] pub influencer_point: Span, - #[label(infer::used_here)] + #[label(used_here)] pub spans: Vec, - #[label(infer::require)] + #[label(require)] pub require_span_as_label: Option, - #[note(infer::require)] + #[note(require)] pub require_span_as_note: Option, - #[note(infer::introduced_by_bound)] + #[note(introduced_by_bound)] pub bound: Option, #[subdiagnostic] From 7ecd064bbe32419eb473b28cdc8e41dd34f20aa9 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 20:45:14 +0300 Subject: [PATCH 23/32] Split infer_explicit_lifetime_required into several diags --- .../locales/en-US/infer.ftl | 15 +++--- compiler/rustc_infer/src/errors/mod.rs | 49 ++++++++++++------- .../nice_region_error/named_anon_conflict.rs | 23 +++++---- 3 files changed, 50 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index f74af62702e99..52babec4f9ea7 100644 --- a/compiler/rustc_error_messages/locales/en-US/infer.ftl +++ b/compiler/rustc_error_messages/locales/en-US/infer.ftl @@ -173,16 +173,15 @@ infer_msl_trait_note = this has an implicit `'static` lifetime requirement infer_msl_trait_sugg = consider relaxing the implicit `'static` requirement infer_suggest_add_let_for_letchains = consider adding `let` -infer_explicit_lifetime_required = explicit lifetime required in {$ident_kind -> - [ident] the type of `{$simple_ident}` - *[param_type] parameter type -} +infer_explicit_lifetime_required_with_ident = explicit lifetime required in the type of `{$simple_ident}` .label = lifetime `{$named}` required -infer_explicit_lifetime_required_sugg = add explicit lifetime `{$named}` to {$ident_kind -> - [ident] the type of `{$simple_ident}` - *[param_type] type -} +infer_explicit_lifetime_required_with_param_type = explicit lifetime required in parameter type + .label = lifetime `{$named}` required + +infer_explicit_lifetime_required_sugg_with_ident = add explicit lifetime `{$named}` to the type of `{$simple_ident}` + +infer_explicit_lifetime_required_sugg_with_param_type = add explicit lifetime `{$named}` to type infer_actual_impl_expl_expected_signature_two = {$leading_ellipsis -> [true] ... diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 51b04eb0df011..9e3def93a6d3d 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -523,23 +523,38 @@ pub struct MismatchedStaticLifetime<'a> { } #[derive(Diagnostic)] -#[diag(infer_explicit_lifetime_required, code = "E0621")] -pub struct ExplicitLifetimeRequired<'a> { - #[primary_span] - #[label] - pub span: Span, - pub ident_kind: &'static str, - pub simple_ident: String, - pub named: String, - - #[suggestion( - infer_explicit_lifetime_required_sugg, - code = "{new_ty}", - applicability = "unspecified" - )] - pub new_ty_span: Span, - #[skip_arg] - pub new_ty: Ty<'a>, +pub enum ExplicitLifetimeRequired<'a> { + #[diag(infer_explicit_lifetime_required_with_ident, code = "E0621")] + WithIdent { + #[primary_span] + #[label] + span: Span, + simple_ident: Ident, + named: String, + #[suggestion( + infer_explicit_lifetime_required_sugg_with_ident, + code = "{new_ty}", + applicability = "unspecified" + )] + new_ty_span: Span, + #[skip_arg] + new_ty: Ty<'a>, + }, + #[diag(infer_explicit_lifetime_required_with_param_type, code = "E0621")] + WithParamType { + #[primary_span] + #[label] + span: Span, + named: String, + #[suggestion( + infer_explicit_lifetime_required_sugg_with_param_type, + code = "{new_ty}", + applicability = "unspecified" + )] + new_ty_span: Span, + #[skip_arg] + new_ty: Ty<'a>, + }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs index d7751158902b8..4e13ec90228d6 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -89,18 +89,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { return None; } - - let simple_ident = param.pat.simple_ident(); - let (ident_kind, simple_ident) = match simple_ident { - Some(ident) => ("ident", ident.to_string()), - None => ("param_type", String::new()), - }; - let named = named.to_string(); - - let err = - ExplicitLifetimeRequired { span, ident_kind, simple_ident, named, new_ty_span, new_ty }; - let err = self.tcx().sess.parse_sess.create_err(err); - Some(err) + let err = match param.pat.simple_ident() { + Some(simple_ident) => ExplicitLifetimeRequired::WithIdent { + span, + simple_ident, + named, + new_ty_span, + new_ty, + }, + None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty }, + }; + Some(self.tcx().sess.parse_sess.create_err(err)) } } From 62f9962eafbf4cf1196d256cf6c559ac397261e1 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 21:50:52 +0300 Subject: [PATCH 24/32] Made ty_or_sig and trait_path use their actual types instead of String --- compiler/rustc_infer/src/errors/mod.rs | 101 ++++++++++++------ .../error_reporting/nice_region_error/mod.rs | 2 +- .../nice_region_error/placeholder_error.rs | 92 ++++++++-------- 3 files changed, 118 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 9e3def93a6d3d..388ddd09905ac 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -1,16 +1,18 @@ use hir::GenericParamKind; use rustc_errors::{ fluent, AddToDiagnostic, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, - MultiSpan, SubdiagnosticMessage, + IntoDiagnosticArg, MultiSpan, SubdiagnosticMessage, }; use rustc_hir as hir; use rustc_hir::FnRetTy; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::{Region, Ty, TyCtxt}; +use rustc_middle::ty::print::TraitRefPrintOnlyTraitPath; +use rustc_middle::ty::{Binder, FnSig, Region, Ty, TyCtxt}; use rustc_span::symbol::kw; use rustc_span::Symbol; use rustc_span::{symbol::Ident, BytePos, Span}; +use crate::infer::error_reporting::nice_region_error::placeholder_error::Highlighted; use crate::infer::error_reporting::{ need_type_info::{GeneratorKindAsDiagArg, UnderspecifiedArgKind}, ObligationCauseAsDiagArg, @@ -557,91 +559,126 @@ pub enum ExplicitLifetimeRequired<'a> { }, } +pub enum TyOrSig<'tcx> { + Ty(Highlighted<'tcx, Ty<'tcx>>), + ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>), +} + +impl IntoDiagnosticArg for TyOrSig<'_> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + match self { + TyOrSig::Ty(ty) => ty.into_diagnostic_arg(), + TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(), + } + } +} + #[derive(Subdiagnostic)] -pub enum ActualImplExplNotes { +pub enum ActualImplExplNotes<'tcx> { #[note(infer_actual_impl_expl_expected_signature_two)] ExpectedSignatureTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_signature_any)] ExpectedSignatureAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_signature_some)] ExpectedSignatureSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_signature_nothing)] - ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedSignatureNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_expected_passive_two)] ExpectedPassiveTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_passive_any)] ExpectedPassiveAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_passive_some)] ExpectedPassiveSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_passive_nothing)] - ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedPassiveNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_expected_other_two)] ExpectedOtherTwo { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, #[note(infer_actual_impl_expl_expected_other_any)] ExpectedOtherAny { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_other_some)] ExpectedOtherSome { leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note(infer_actual_impl_expl_expected_other_nothing)] - ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + ExpectedOtherNothing { + leading_ellipsis: bool, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + }, #[note(infer_actual_impl_expl_but_actually_implements_trait)] - ButActuallyImplementsTrait { trait_path: String, has_lifetime: bool, lifetime: usize }, + ButActuallyImplementsTrait { + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + has_lifetime: bool, + lifetime: usize, + }, #[note(infer_actual_impl_expl_but_actually_implemented_for_ty)] ButActuallyImplementedForTy { - trait_path: String, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, ty: String, }, #[note(infer_actual_impl_expl_but_actually_ty_implements)] - ButActuallyTyImplements { trait_path: String, has_lifetime: bool, lifetime: usize, ty: String }, + ButActuallyTyImplements { + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, } pub enum ActualImplExpectedKind { @@ -657,13 +694,13 @@ pub enum ActualImplExpectedLifetimeKind { Nothing, } -impl ActualImplExplNotes { +impl<'tcx> ActualImplExplNotes<'tcx> { pub fn new_expected( kind: ActualImplExpectedKind, lt_kind: ActualImplExpectedLifetimeKind, leading_ellipsis: bool, - ty_or_sig: String, - trait_path: String, + ty_or_sig: TyOrSig<'tcx>, + trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, ) -> Self { @@ -728,7 +765,7 @@ impl ActualImplExplNotes { #[derive(Diagnostic)] #[diag(infer_trait_placeholder_mismatch)] -pub struct TraitPlaceholderMismatch { +pub struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, #[label(label_satisfy)] @@ -741,7 +778,7 @@ pub struct TraitPlaceholderMismatch { pub trait_def_id: String, #[subdiagnostic(eager)] - pub actual_impl_expl_notes: Vec, + pub actual_impl_expl_notes: Vec>, } pub struct ConsiderBorrowingParamHelp { diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs index 8a0e332f9c704..59fb74eb54378 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mod.rs @@ -9,7 +9,7 @@ mod different_lifetimes; pub mod find_anon_type; mod mismatched_static_lifetime; mod named_anon_conflict; -mod placeholder_error; +pub(crate) mod placeholder_error; mod placeholder_relation; mod static_impl_trait; mod trait_impl_difference; diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 904723c4da9d7..2ff2d1926a260 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,6 +1,6 @@ use crate::errors::{ ActualImplExpectedKind, ActualImplExpectedLifetimeKind, ActualImplExplNotes, - TraitPlaceholderMismatch, + TraitPlaceholderMismatch, TyOrSig, }; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; @@ -8,7 +8,7 @@ use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; +use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, IntoDiagnosticArg}; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::ExpectedFound; @@ -18,6 +18,42 @@ use rustc_middle::ty::{self, RePlaceholder, ReVar, Region, TyCtxt}; use std::fmt; +// HACK(eddyb) maybe move this in a more central location. +#[derive(Copy, Clone)] +pub struct Highlighted<'tcx, T> { + tcx: TyCtxt<'tcx>, + highlight: RegionHighlightMode<'tcx>, + value: T, +} + +impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T> +where + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, +{ + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + rustc_errors::DiagnosticArgValue::Str(self.to_string().into()) + } +} + +impl<'tcx, T> Highlighted<'tcx, T> { + fn map(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> { + Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) } + } +} + +impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> +where + T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>, Error = fmt::Error, Output = FmtPrinter<'a, 'tcx>>, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); + printer.region_highlight_mode = self.highlight; + + let s = self.value.print(printer)?.into_buffer(); + f.write_str(&s) + } +} + impl<'tcx> NiceRegionError<'_, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and /// an anonymous region, emit a descriptive diagnostic error. @@ -328,39 +364,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { actual_has_vid: Option, any_self_ty_has_vid: bool, leading_ellipsis: bool, - ) -> Vec { - // HACK(eddyb) maybe move this in a more central location. - #[derive(Copy, Clone)] - struct Highlighted<'tcx, T> { - tcx: TyCtxt<'tcx>, - highlight: RegionHighlightMode<'tcx>, - value: T, - } - - impl<'tcx, T> Highlighted<'tcx, T> { - fn map(self, f: impl FnOnce(T) -> U) -> Highlighted<'tcx, U> { - Highlighted { tcx: self.tcx, highlight: self.highlight, value: f(self.value) } - } - } - - impl<'tcx, T> fmt::Display for Highlighted<'tcx, T> - where - T: for<'a> Print< - 'tcx, - FmtPrinter<'a, 'tcx>, - Error = fmt::Error, - Output = FmtPrinter<'a, 'tcx>, - >, - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut printer = ty::print::FmtPrinter::new(self.tcx, Namespace::TypeNS); - printer.region_highlight_mode = self.highlight; - - let s = self.value.print(printer)?.into_buffer(); - f.write_str(&s) - } - } - + ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: // @@ -418,27 +422,27 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { }); ( ActualImplExpectedKind::Signature, - closure_sig.to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::ClosureSig(closure_sig), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } else { ( ActualImplExpectedKind::Other, - self_ty.to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(self_ty), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } } else if passive_voice { ( ActualImplExpectedKind::Passive, - expected_trait_ref.map(|tr| tr.self_ty()).to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) } else { ( ActualImplExpectedKind::Other, - expected_trait_ref.map(|tr| tr.self_ty()).to_string(), - expected_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(), + TyOrSig::Ty(expected_trait_ref.map(|tr| tr.self_ty())), + expected_trait_ref.map(|tr| tr.print_only_trait_path()), ) }; @@ -474,7 +478,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { None => true, }; - let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()).to_string(); + let trait_path = actual_trait_ref.map(|tr| tr.print_only_trait_path()); let ty = actual_trait_ref.map(|tr| tr.self_ty()).to_string(); let has_lifetime = actual_has_vid.is_some(); let lifetime = actual_has_vid.unwrap_or_default(); From a86173766c113fdde95c2510de5909d4f9469833 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Thu, 3 Nov 2022 21:56:15 +0300 Subject: [PATCH 25/32] Fix nits --- .../error_reporting/nice_region_error/placeholder_error.rs | 6 ++---- .../error_reporting/nice_region_error/static_impl_trait.rs | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index 2ff2d1926a260..a5e5f9538565b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -333,7 +333,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { leading_ellipsis, ); - let diag = TraitPlaceholderMismatch { + self.tcx().sess.create_err(TraitPlaceholderMismatch { span, satisfy_span, where_span, @@ -341,9 +341,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { def_id, trait_def_id: self.tcx().def_path_str(trait_def_id), actual_impl_expl_notes, - }; - - self.tcx().sess.create_err(diag) + }) } /// Add notes with details about the expected and actual trait refs, with attention to cases diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index fbc71bd7e0196..ae3f174c72e64 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { AssocItemContainer::ImplContainer => (false, String::new()), }; - let diag = ButCallingIntroduces { + let mut err = self.tcx().sess.create_err(ButCallingIntroduces { param_ty_span: param.param_ty_span, cause_span: cause.span, has_param_name: simple_ident.is_some(), @@ -73,8 +73,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { assoc_item: ctxt.assoc_item.name, has_impl_path, impl_path, - }; - let mut err = self.tcx().sess.create_err(diag); + }); if self.find_impl_on_dyn_trait(&mut err, param.param_ty, &ctxt) { let reported = err.emit(); return Some(reported); From dda3ebad0a2b26ee35e2f4f3d26f529b092edfc4 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Mon, 7 Nov 2022 15:56:52 +0300 Subject: [PATCH 26/32] Fix broken rebase --- .../error_reporting/nice_region_error/static_impl_trait.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs index ae3f174c72e64..8a6dadf935f42 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -8,7 +8,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCauseCode, UnifyReceiverContext}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{AddToDiagnostic, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{walk_ty, Visitor}; From 2a8b17dbc5489ee085cf1587cf3c63a3fd2746aa Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Tue, 29 Nov 2022 19:19:26 +0300 Subject: [PATCH 27/32] Fix formatting --- .../error_reporting/nice_region_error/placeholder_error.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index a5e5f9538565b..202f39521e967 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -405,8 +405,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut self_ty = expected_trait_ref.map(|tr| tr.self_ty()); self_ty.highlight.maybe_highlighting_region(vid, actual_has_vid); - if self_ty.value.is_closure() - && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) + if self_ty.value.is_closure() && self.tcx().is_fn_trait(expected_trait_ref.value.def_id) { let closure_sig = self_ty.map(|closure| { if let ty::Closure(_, substs) = closure.kind() { From 0c50e1f146efc594eb84146c598d577c9f8a27d2 Mon Sep 17 00:00:00 2001 From: Nikita Tomashevich Date: Wed, 28 Dec 2022 15:24:18 +0300 Subject: [PATCH 28/32] eager is the default now --- compiler/rustc_infer/src/errors/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 388ddd09905ac..9cd053694fe45 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -777,7 +777,7 @@ pub struct TraitPlaceholderMismatch<'tcx> { pub def_id: String, pub trait_def_id: String, - #[subdiagnostic(eager)] + #[subdiagnostic] pub actual_impl_expl_notes: Vec>, } From ce6b7179afcdf6ae2dad7e69c56f1f5c957b47bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Jan 2023 21:29:36 +0000 Subject: [PATCH 29/32] Detect closures assigned to binding in block Fix #58497. --- .../rustc_borrowck/src/borrowck_errors.rs | 7 ++--- .../src/diagnostics/conflict_errors.rs | 31 ++++++++++++++++--- .../src/diagnostics/explain_borrow.rs | 12 +++++-- .../src/diagnostics/region_name.rs | 2 +- .../diagnostics/borrowck/borrowck-3.rs | 3 +- .../diagnostics/borrowck/borrowck-3.stderr | 26 +++++++++------- .../unboxed-closure-region.rs | 2 +- .../unboxed-closure-region.stderr | 25 +++++++++------ src/tools/rustfmt/tests/target/issue_4110.rs | 1 + 9 files changed, 74 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index e4942f9b666e0..a4943d112042d 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -440,15 +440,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { closure_kind: &str, borrowed_path: &str, capture_span: Span, + scope: &str, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { let mut err = struct_span_err!( self, closure_span, E0373, - "{} may outlive the current function, but it borrows {}, which is owned by the current \ - function", - closure_kind, - borrowed_path, + "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \ + which is owned by the current {scope}", ); err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 492c8d0201267..d99bfc01a4298 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1423,6 +1423,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // // then just use the normal error. The closure isn't escaping // and `move` will not help here. + ( + Some(name), + BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _), + ) => self.report_escaping_closure_capture( + borrow_spans, + borrow_span, + &RegionName { + name: self.synthesize_region_name(), + source: RegionNameSource::Static, + }, + ConstraintCategory::CallArgument(None), + var_or_use_span, + &format!("`{}`", name), + "block", + ), ( Some(name), BorrowExplanation::MustBeValidFor { @@ -1443,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category, span, &format!("`{}`", name), + "function", ), ( name, @@ -1895,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(err) } + #[instrument(level = "debug", skip(self))] fn report_escaping_closure_capture( &mut self, use_span: UseSpans<'tcx>, @@ -1903,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { category: ConstraintCategory<'tcx>, constraint_span: Span, captured_var: &str, + scope: &str, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { let tcx = self.infcx.tcx; let args_span = use_span.args_or_use(); @@ -1933,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None => "closure", }; - let mut err = - self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span); + let mut err = self.cannot_capture_in_long_lived_closure( + args_span, + kind, + captured_var, + var_span, + scope, + ); err.span_suggestion_verbose( sugg_span, &format!( @@ -1956,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) { err.note( "async blocks are not executed immediately and must either take a \ - reference or ownership of outside variables they use", + reference or ownership of outside variables they use", ); } else { - let msg = format!("function requires argument type to outlive `{}`", fr_name); + let msg = format!("{scope} requires argument type to outlive `{fr_name}`"); err.span_note(constraint_span, &msg); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 00f5e8a83972f..c4ae30151c4bd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// First span returned points to the location of the conflicting use /// Second span if `Some` is returned in the case of closures and points /// to the use of the path + #[instrument(level = "debug", skip(self))] fn later_use_kind( &self, borrow: &BorrowData<'tcx>, @@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let block = &self.body.basic_blocks[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)), + kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)), .. }) = block.statements.get(location.statement_index) { - LaterUseKind::FakeLetRead + if let Some(l) = place.as_local() + && let local_decl = &self.body.local_decls[l] + && local_decl.ty.is_closure() + { + LaterUseKind::ClosureCapture + } else { + LaterUseKind::FakeLetRead + } } else if self.was_captured_by_trait_object(borrow) { LaterUseKind::TraitCapture } else if location.statement_index == block.statements.len() { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index dbd4cac7b1432..579ce90a760f2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { /// increment the counter. /// /// This is _not_ idempotent. Call `give_region_a_name` when possible. - fn synthesize_region_name(&self) -> Symbol { + pub(crate) fn synthesize_region_name(&self) -> Symbol { let c = self.next_region_name.replace_with(|counter| *counter + 1); Symbol::intern(&format!("'{:?}", c)) } diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs index bdd6cb79b60b0..00f50c33e1ccd 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -8,10 +8,9 @@ struct Point { fn main() { let mut c = { let mut p = Point {x: "1".to_string(), y: "2".to_string() }; - || { + || { //~ ERROR closure may outlive the current block, but it borrows `p` let x = &mut p.x; println!("{:?}", p); - //~^ ERROR `p` does not live long enough } }; c(); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr index dab1809a381ee..ee92380478685 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -1,18 +1,22 @@ -error[E0597]: `p` does not live long enough - --> $DIR/borrowck-3.rs:13:29 +error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block + --> $DIR/borrowck-3.rs:11:9 | -LL | let mut c = { - | ----- borrow later stored here -LL | let mut p = Point {x: "1".to_string(), y: "2".to_string() }; LL | || { - | -- value captured here + | ^^ may outlive borrowed value `p` LL | let x = &mut p.x; LL | println!("{:?}", p); - | ^ borrowed value does not live long enough -... -LL | }; - | - `p` dropped here while still borrowed + | - `p` is borrowed here + | +note: block requires argument type to outlive `'1` + --> $DIR/borrowck-3.rs:9:9 + | +LL | let mut c = { + | ^^^^^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | move || { + | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.rs b/src/test/ui/unboxed-closures/unboxed-closure-region.rs index f202492eda553..51fe118c93ff1 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-region.rs +++ b/src/test/ui/unboxed-closures/unboxed-closure-region.rs @@ -5,7 +5,7 @@ fn main() { let _f = { let x = 0; - || x //~ ERROR `x` does not live long enough + || x //~ ERROR closure may outlive the current block, but it borrows `x` }; _f; } diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr index b40b2f67d9bad..43e9af24a7c2b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-region.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-region.stderr @@ -1,16 +1,21 @@ -error[E0597]: `x` does not live long enough - --> $DIR/unboxed-closure-region.rs:8:12 +error[E0373]: closure may outlive the current block, but it borrows `x`, which is owned by the current block + --> $DIR/unboxed-closure-region.rs:8:9 | -LL | let _f = { - | -- borrow later stored here -LL | let x = 0; LL | || x - | -- ^ borrowed value does not live long enough + | ^^ - `x` is borrowed here | | - | value captured here -LL | }; - | - `x` dropped here while still borrowed + | may outlive borrowed value `x` + | +note: block requires argument type to outlive `'1` + --> $DIR/unboxed-closure-region.rs:6:9 + | +LL | let _f = { + | ^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | move || x + | ++++ error: aborting due to previous error -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/src/tools/rustfmt/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs index 4a58c3946e12d..d3734e90b7ffa 100644 --- a/src/tools/rustfmt/tests/target/issue_4110.rs +++ b/src/tools/rustfmt/tests/target/issue_4110.rs @@ -20,6 +20,7 @@ fn bindings() { category, span, &format!("`{}`", name), + "function", ), ( ref name, From 43bec832667252ea2e78abe17918ba5fbbc1e27d Mon Sep 17 00:00:00 2001 From: Ezra Shaw Date: Sat, 7 Jan 2023 17:08:04 +1300 Subject: [PATCH 30/32] docs: make `HashSet::retain` doctest more clear --- library/std/src/collections/hash/set.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index cee884145c711..b59f89d321c47 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -317,7 +317,7 @@ impl HashSet { /// /// let mut set = HashSet::from([1, 2, 3, 4, 5, 6]); /// set.retain(|&k| k % 2 == 0); - /// assert_eq!(set.len(), 3); + /// assert_eq!(set, HashSet::from([2, 4, 6])); /// ``` /// /// # Performance From a7ac923088e6088be6c16c27dd9dca07bad7a391 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 6 Jan 2023 22:21:54 -0700 Subject: [PATCH 31/32] rustdoc: remove no-op mobile CSS `.content { margin-left: 0 }` This rule was added to override non-zero left margin on `.content`, which was removed in 135281ed1525db15edd8ebd092aa10aa40df2386 and the margin-left was put on the docblock. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 05a12d3d4d4a2..c1ed0ccef886c 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1655,10 +1655,6 @@ in storage.js margin-top: 1em; } - .content { - margin-left: 0px; - } - .anchor { display: none !important; } From a139fd06277dd714b5244fcbb621488e1da2d518 Mon Sep 17 00:00:00 2001 From: Folyd Date: Sat, 7 Jan 2023 23:50:07 +0800 Subject: [PATCH 32/32] Change to immutable borrow when cloning element of RepeatN --- library/core/src/iter/sources/repeat_n.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs index fd8d25ce1a55e..dc61d6065b8ed 100644 --- a/library/core/src/iter/sources/repeat_n.rs +++ b/library/core/src/iter/sources/repeat_n.rs @@ -126,7 +126,7 @@ impl Iterator for RepeatN { // zero so it won't be dropped later, and thus it's okay to take it here. unsafe { ManuallyDrop::take(&mut self.element) } } else { - A::clone(&mut self.element) + A::clone(&self.element) }) }