diff --git a/compiler/rustc_error_messages/locales/en-US/infer.ftl b/compiler/rustc_error_messages/locales/en-US/infer.ftl index 8cfd20c6eda..4a43d150968 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 edd9eca24cb..69fc3be2bc3 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -544,25 +544,177 @@ pub struct ExplicitLifetimeRequired<'a> { #[derive(Subdiagnostic)] pub enum ActualImplExplNotes { - // Field names have to be different across all variants - #[note(infer::actual_impl_expl_expected)] - Expected { + // Field names have to be different across Expected* and ButActually variants + #[note(infer::actual_impl_expl_expected_signature_two)] + ExpectedSignatureTwo { leading_ellipsis: bool, - kind: &'static str, ty_or_sig: String, trait_path: String, - lt_kind: &'static str, lifetime_1: usize, lifetime_2: usize, }, - #[note(infer::actual_impl_expl_but_actually)] - ButActually { - kind_2: &'static str, + #[note(infer::actual_impl_expl_expected_signature_any)] + ExpectedSignatureAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_some)] + ExpectedSignatureSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_signature_nothing)] + ExpectedSignatureNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_passive_two)] + ExpectedPassiveTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_any)] + ExpectedPassiveAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_some)] + ExpectedPassiveSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_passive_nothing)] + ExpectedPassiveNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_expected_other_two)] + ExpectedOtherTwo { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + }, + #[note(infer::actual_impl_expl_expected_other_any)] + ExpectedOtherAny { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_some)] + ExpectedOtherSome { + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + }, + #[note(infer::actual_impl_expl_expected_other_nothing)] + ExpectedOtherNothing { leading_ellipsis: bool, ty_or_sig: String, trait_path: String }, + #[note(infer::actual_impl_expl_but_actually_implements_trait)] + ButActuallyImplementsTrait { trait_path_2: String, has_lifetime: bool, lifetime: usize }, + #[note(infer::actual_impl_expl_but_actually_implemented_for_ty)] + ButActuallyImplementedForTy { trait_path_2: String, has_lifetime: bool, lifetime: usize, ty: String, }, + #[note(infer::actual_impl_expl_but_actually_ty_implements)] + ButActuallyTyImplements { + trait_path_2: String, + has_lifetime: bool, + lifetime: usize, + ty: String, + }, +} + +pub enum ActualImplExpectedKind { + Signature, + Passive, + Other, +} + +pub enum ActualImplExpectedLifetimeKind { + Two, + Any, + Some, + Nothing, +} + +impl ActualImplExplNotes { + pub fn new_expected( + kind: ActualImplExpectedKind, + lt_kind: ActualImplExpectedLifetimeKind, + leading_ellipsis: bool, + ty_or_sig: String, + trait_path: String, + lifetime_1: usize, + lifetime_2: usize, + ) -> Self { + match (kind, lt_kind) { + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedSignatureTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedPassiveTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => { + Self::ExpectedOtherTwo { + leading_ellipsis, + ty_or_sig, + trait_path, + lifetime_1, + lifetime_2, + } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => { + Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => { + Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + } + (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => { + Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path } + } + } + } } #[derive(Diagnostic)] diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs index cf1032f7006..d2fd4f6cd7c 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] }