From 5646b65cf58123679fdf4ef489f690d1b21e1436 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Thu, 18 Apr 2024 19:18:35 +0000 Subject: [PATCH 1/4] Pass translation closure to add_to_diag_with() as reference --- compiler/rustc_ast_lowering/src/errors.rs | 2 +- compiler/rustc_ast_passes/src/errors.rs | 4 ++-- compiler/rustc_builtin_macros/src/errors.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 6 +++--- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- compiler/rustc_hir_typeck/src/errors.rs | 6 +++--- compiler/rustc_infer/src/errors/mod.rs | 18 +++++++++--------- .../rustc_infer/src/errors/note_and_explain.rs | 2 +- compiler/rustc_lint/src/errors.rs | 2 +- compiler/rustc_lint/src/lints.rs | 18 +++++++++--------- .../src/diagnostics/subdiagnostic.rs | 2 +- compiler/rustc_mir_build/src/errors.rs | 4 ++-- compiler/rustc_parse/src/errors.rs | 2 +- compiler/rustc_passes/src/errors.rs | 2 +- compiler/rustc_pattern_analysis/src/errors.rs | 4 ++-- compiler/rustc_trait_selection/src/errors.rs | 2 +- .../ui-fulldeps/internal-lints/diagnostics.rs | 4 ++-- 17 files changed, 41 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs index ca0821e2c9edb..6799513a323c4 100644 --- a/compiler/rustc_ast_lowering/src/errors.rs +++ b/compiler/rustc_ast_lowering/src/errors.rs @@ -44,7 +44,7 @@ impl Subdiagnostic for InvalidAbiReason { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { #[allow(rustc::untranslatable_diagnostic)] diag.note(self.0); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index f397c949e0486..25a125f83935b 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -382,7 +382,7 @@ impl Subdiagnostic for EmptyLabelManySpans { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { diag.span_labels(self.0, ""); } @@ -751,7 +751,7 @@ impl Subdiagnostic for StableFeature { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { diag.arg("name", self.name); diag.arg("since", self.since); diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 6b6647ef085c2..9078dc07a3152 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -601,7 +601,7 @@ impl Subdiagnostic for FormatUnusedArg { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { diag.arg("named", self.named); let msg = f(diag, crate::fluent_generated::builtin_macros_format_unused_arg.into()); diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a17e0da47a5cf..6c84eeaf888d7 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -177,7 +177,7 @@ where { /// Add a subdiagnostic to an existing diagnostic. fn add_to_diag(self, diag: &mut Diag<'_, G>) { - self.add_to_diag_with(diag, |_, m| m); + self.add_to_diag_with(diag, &|_, m| m); } /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used @@ -185,7 +185,7 @@ where fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ); } @@ -1197,7 +1197,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { dcx: &crate::DiagCtxt, subdiagnostic: impl Subdiagnostic, ) -> &mut Self { - subdiagnostic.add_to_diag_with(self, |diag, msg| { + subdiagnostic.add_to_diag_with(self, &|diag, msg| { let args = diag.args.iter(); let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); dcx.eagerly_translate(msg, args) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 6c0551848d688..1ef945985be0a 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -302,7 +302,7 @@ impl Subdiagnostic for SingleLabelManySpans { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { diag.span_labels(self.spans, self.label); } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 3dc9c7b86f713..1c4d5657b171e 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -191,7 +191,7 @@ impl Subdiagnostic for TypeMismatchFruTypo { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); @@ -370,7 +370,7 @@ impl Subdiagnostic for RemoveSemiForCoerce { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label(self.expr, fluent::hir_typeck_remove_semi_for_coerce_expr); @@ -546,7 +546,7 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { match self { CastUnknownPointerSub::To(span) => { diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs index 4593108edac03..2acaeac24398d 100644 --- a/compiler/rustc_infer/src/errors/mod.rs +++ b/compiler/rustc_infer/src/errors/mod.rs @@ -239,7 +239,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let mut label_or_note = |span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); @@ -304,7 +304,7 @@ impl Subdiagnostic for LifetimeMismatchLabels { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { @@ -352,7 +352,7 @@ impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let mut mk_suggestion = || { let ( @@ -454,7 +454,7 @@ impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { fn add_to_diag_with>( mut self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { self.unmet_requirements .push_span_label(self.binding_span, fluent::infer_msl_introduces_static); @@ -773,7 +773,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { @@ -818,7 +818,7 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { let mut multi_span: MultiSpan = vec![self.span].into(); multi_span.push_span_label(self.span, fluent::infer_dtcs_has_lifetime_req_label); @@ -865,7 +865,7 @@ impl Subdiagnostic for ReqIntroducedLocations { fn add_to_diag_with>( mut self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { for sp in self.spans { self.span.push_span_label(sp, fluent::infer_ril_introduced_here); @@ -888,7 +888,7 @@ impl Subdiagnostic for MoreTargeted { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.code(E0772); diag.primary_message(fluent::infer_more_targeted); @@ -1293,7 +1293,7 @@ impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { diag.arg("path", self.path); let message = f(diag, crate::fluent_generated::infer_stp_wrap_many.into()); diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs index 7b962b0140808..70d94873530e7 100644 --- a/compiler/rustc_infer/src/errors/note_and_explain.rs +++ b/compiler/rustc_infer/src/errors/note_and_explain.rs @@ -163,7 +163,7 @@ impl Subdiagnostic for RegionExplanation<'_> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { diag.arg("pref_kind", self.prefix); diag.arg("suff_kind", self.suffix); diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs index ee99e824a548b..c23d1221bc866 100644 --- a/compiler/rustc_lint/src/errors.rs +++ b/compiler/rustc_lint/src/errors.rs @@ -27,7 +27,7 @@ impl Subdiagnostic for OverruledAttributeSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { OverruledAttributeSub::DefaultSource { id } => { diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index a034bebc85ec0..74a0a224dba4c 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -274,7 +274,7 @@ impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { // Access to associates types should use `::Assoc`, which does not need a // bound. Let's see if this type does that. @@ -330,7 +330,7 @@ impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.multipart_suggestion( fluent::lint_suggestion, @@ -451,7 +451,7 @@ impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let mut err = self.err; loop { @@ -506,7 +506,7 @@ impl Subdiagnostic for BuiltinClashingExternSub<'_> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let mut expected_str = DiagStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); @@ -788,7 +788,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); @@ -806,7 +806,7 @@ impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { @@ -954,7 +954,7 @@ impl Subdiagnostic for NonBindingLetSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; @@ -1240,7 +1240,7 @@ impl Subdiagnostic for NonSnakeCaseDiagSub { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { NonSnakeCaseDiagSub::Label { span } => { @@ -1482,7 +1482,7 @@ impl Subdiagnostic for OverflowingBinHexSign { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { OverflowingBinHexSign::Positive => { diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index ced782cdbc016..9491426688444 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -90,7 +90,7 @@ impl SubdiagnosticDerive { fn add_to_diag_with<__G, __F>( self, #diag: &mut rustc_errors::Diag<'_, __G>, - #f: __F + #f: &__F ) where __G: rustc_errors::EmissionGuarantee, __F: rustc_errors::SubdiagMessageOp<__G>, diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 9ddfb12bf7643..f67113afd6d9d 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -423,7 +423,7 @@ impl Subdiagnostic for UnsafeNotInheritedLintNote { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.span_note(self.signature_span, fluent::mir_build_unsafe_fn_safe_body); let body_start = self.body_span.shrink_to_lo(); @@ -871,7 +871,7 @@ impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index eae2d904c35e1..a5d18a919c4a5 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1463,7 +1463,7 @@ impl Subdiagnostic for FnTraitMissingParen { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { diag.span_label(self.span, crate::fluent_generated::parse_fn_trait_missing_paren); let applicability = if self.machine_applicable { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 3f26ea4507d41..27e0ddc64d9d5 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1755,7 +1755,7 @@ impl Subdiagnostic for UnusedVariableStringInterp { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { diag.span_label(self.lit, crate::fluent_generated::passes_maybe_string_interpolation); diag.multipart_suggestion( diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs index 75b7b7c8f6784..27f227e6d9c11 100644 --- a/compiler/rustc_pattern_analysis/src/errors.rs +++ b/compiler/rustc_pattern_analysis/src/errors.rs @@ -65,7 +65,7 @@ impl<'tcx> Subdiagnostic for Overlap<'tcx> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { let Overlap { span, range } = self; @@ -113,7 +113,7 @@ impl<'tcx> Subdiagnostic for GappedRange<'tcx> { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _: F, + _: &F, ) { let GappedRange { span, gap, first_range } = self; diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index b126062102eda..9b08a86ef1604 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -104,7 +104,7 @@ impl Subdiagnostic for AdjustSignatureBorrow { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - _f: F, + _f: &F, ) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs index 1d7417be58cc3..380b2b6c431d5 100644 --- a/tests/ui-fulldeps/internal-lints/diagnostics.rs +++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs @@ -59,7 +59,7 @@ impl Subdiagnostic for UntranslatableInAddtoDiag { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { diag.note("untranslatable diagnostic"); //~^ ERROR diagnostics should be created using translatable messages @@ -72,7 +72,7 @@ impl Subdiagnostic for TranslatableInAddtoDiag { fn add_to_diag_with>( self, diag: &mut Diag<'_, G>, - f: F, + f: &F, ) { diag.note(crate::fluent_generated::no_crate_note); } From c88bb6c011a034a8b29d2a61734de0d36a02a1e9 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 20 Apr 2024 12:52:05 +0000 Subject: [PATCH 2/4] Allow nesting subdiagnostics --- .../src/diagnostics/subdiagnostic.rs | 37 +++++++++++++------ compiler/rustc_macros/src/lib.rs | 1 + .../subdiagnostic-derive.rs | 10 +++++ 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 9491426688444..45236771bce63 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -71,6 +71,7 @@ impl SubdiagnosticDerive { span_field: None, applicability: None, has_suggestion_parts: false, + has_subdiagnostic: false, is_enum, }; builder.into_tokens().unwrap_or_else(|v| v.to_compile_error()) @@ -133,6 +134,10 @@ struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> { /// during finalization if still `false`. has_suggestion_parts: bool, + /// Set to true when a `#[subdiagnostic]` field is encountered, used to suppress the error + /// emitted when no subdiagnostic kinds are specified on the variant itself. + has_subdiagnostic: bool, + /// Set to true when this variant is an enum variant rather than just the body of a struct. is_enum: bool, } @@ -373,6 +378,13 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { Ok(quote! {}) } + "subdiagnostic" => { + let f = &self.parent.f; + let diag = &self.parent.diag; + let binding = &info.binding; + self.has_subdiagnostic = true; + Ok(quote! { #binding.add_to_diag_with(#diag, #f); }) + } _ => { let mut span_attrs = vec![]; if kind_stats.has_multipart_suggestion { @@ -480,18 +492,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { pub(crate) fn into_tokens(&mut self) -> Result { let kind_slugs = self.identify_kind()?; - if kind_slugs.is_empty() { - if self.is_enum { - // It's okay for a variant to not be a subdiagnostic at all.. - return Ok(quote! {}); - } else { - // ..but structs should always be _something_. - throw_span_err!( - self.variant.ast().ident.span().unwrap(), - "subdiagnostic kind not specified" - ); - } - }; let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect(); @@ -510,6 +510,19 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { .map(|binding| self.generate_field_attr_code(binding, kind_stats)) .collect(); + if kind_slugs.is_empty() { + if self.is_enum { + // It's okay for a variant to not be a subdiagnostic at all.. + return Ok(quote! {}); + } else if !self.has_subdiagnostic { + // ..but structs should always be _something_. + throw_span_err!( + self.variant.ast().ident.span().unwrap(), + "subdiagnostic kind not specified" + ); + } + }; + let span_field = self.span_field.value_ref(); let diag = &self.parent.diag; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index eedc508fb1461..c7b7eadbd9d6b 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -144,6 +144,7 @@ decl_derive!( help, note, warning, + subdiagnostic, suggestion, suggestion_short, suggestion_hidden, diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index 163af7ff0e214..659ae54f7a3be 100644 --- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -827,3 +827,13 @@ struct PrimarySpanOnVec { //~| NOTE there must be exactly one primary span sub: Vec, } + +#[derive(Subdiagnostic)] +struct NestedParent { + #[subdiagnostic] + single_sub: A, + #[subdiagnostic] + option_sub: Option, + #[subdiagnostic] + vec_sub: Vec, +} From b220b741c6d4e16e34d183b38d6384d369c9a620 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 20 Apr 2024 12:57:29 +0000 Subject: [PATCH 3/4] Fix source ordering of IntoDiagArg impls --- compiler/rustc_errors/src/diagnostic_impls.rs | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 1ef945985be0a..93b1c6775d673 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -227,6 +227,36 @@ impl IntoDiagArg for rustc_lint_defs::Level { } } +impl IntoDiagArg for hir::def::Res { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::Borrowed(self.descr())) + } +} + +impl IntoDiagArg for DiagLocation { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::from(self.to_string())) + } +} + +impl IntoDiagArg for Backtrace { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::from(self.to_string())) + } +} + +impl IntoDiagArg for Level { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(Cow::from(self.to_string())) + } +} + +impl IntoDiagArg for type_ir::ClosureKind { + fn into_diag_arg(self) -> DiagArgValue { + DiagArgValue::Str(self.as_str().into()) + } +} + #[derive(Clone)] pub struct DiagSymbolList(Vec); @@ -244,12 +274,6 @@ impl IntoDiagArg for DiagSymbolList { } } -impl IntoDiagArg for hir::def::Res { - fn into_diag_arg(self) -> DiagArgValue { - DiagArgValue::Str(Cow::Borrowed(self.descr())) - } -} - impl Diagnostic<'_, G> for TargetDataLayoutErrors<'_> { fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> { match self { @@ -316,24 +340,6 @@ pub struct ExpectedLifetimeParameter { pub count: usize, } -impl IntoDiagArg for DiagLocation { - fn into_diag_arg(self) -> DiagArgValue { - DiagArgValue::Str(Cow::from(self.to_string())) - } -} - -impl IntoDiagArg for Backtrace { - fn into_diag_arg(self) -> DiagArgValue { - DiagArgValue::Str(Cow::from(self.to_string())) - } -} - -impl IntoDiagArg for Level { - fn into_diag_arg(self) -> DiagArgValue { - DiagArgValue::Str(Cow::from(self.to_string())) - } -} - #[derive(Subdiagnostic)] #[suggestion(errors_indicate_anonymous_lifetime, code = "{suggestion}", style = "verbose")] pub struct IndicateAnonymousLifetime { @@ -342,9 +348,3 @@ pub struct IndicateAnonymousLifetime { pub count: usize, pub suggestion: String, } - -impl IntoDiagArg for type_ir::ClosureKind { - fn into_diag_arg(self) -> DiagArgValue { - DiagArgValue::Str(self.as_str().into()) - } -} From 6974e9cf7012b0f3e2a58a8accde23007274f9a9 Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 20 Apr 2024 13:21:15 +0000 Subject: [PATCH 4/4] Move "elided lifetime in path" to subdiagnostic struct This requires nested subdiagnostics. --- compiler/rustc_errors/src/diagnostic_impls.rs | 8 +++++ compiler/rustc_errors/src/lib.rs | 33 +++++++++---------- .../rustc_lint/src/context/diagnostics.rs | 18 +++++----- compiler/rustc_resolve/src/errors.rs | 4 ++- compiler/rustc_resolve/src/late.rs | 12 +++---- 5 files changed, 41 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 93b1c6775d673..2b10fcd8d6ab0 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -348,3 +348,11 @@ pub struct IndicateAnonymousLifetime { pub count: usize, pub suggestion: String, } + +#[derive(Subdiagnostic)] +pub struct ElidedLifetimeInPathSubdiag { + #[subdiagnostic] + pub expected: ExpectedLifetimeParameter, + #[subdiagnostic] + pub indicate: Option, +} diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 8d6b22a9fa988..02b7ec188784c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -41,8 +41,8 @@ pub use diagnostic::{ SubdiagMessageOp, Subdiagnostic, }; pub use diagnostic_impls::{ - DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime, - SingleLabelManySpans, + DiagArgFromDisplay, DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, + IndicateAnonymousLifetime, SingleLabelManySpans, }; pub use emitter::ColorConfig; pub use rustc_error_messages::{ @@ -1912,27 +1912,24 @@ impl Level { } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. -pub fn add_elided_lifetime_in_path_suggestion( +pub fn elided_lifetime_in_path_suggestion( source_map: &SourceMap, - diag: &mut Diag<'_, G>, n: usize, path_span: Span, incl_angl_brckt: bool, insertion_span: Span, -) { - diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n }); - if !source_map.is_span_accessible(insertion_span) { - // Do not try to suggest anything if generated by a proc-macro. - return; - } - let anon_lts = vec!["'_"; n].join(", "); - let suggestion = - if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") }; - - diag.subdiagnostic( - diag.dcx, - IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }, - ); +) -> ElidedLifetimeInPathSubdiag { + let expected = ExpectedLifetimeParameter { span: path_span, count: n }; + // Do not try to suggest anything if generated by a proc-macro. + let indicate = source_map.is_span_accessible(insertion_span).then(|| { + let anon_lts = vec!["'_"; n].join(", "); + let suggestion = + if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") }; + + IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion } + }); + + ElidedLifetimeInPathSubdiag { expected, indicate } } pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index b2403836397a1..8458b53933537 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -2,7 +2,7 @@ #![allow(rustc::untranslatable_diagnostic)] use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS; -use rustc_errors::{add_elided_lifetime_in_path_suggestion, Diag}; +use rustc_errors::{elided_lifetime_in_path_suggestion, Diag}; use rustc_errors::{Applicability, SuggestionStyle}; use rustc_middle::middle::stability; use rustc_session::lint::BuiltinLintDiag; @@ -74,13 +74,15 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di diag.span_note(span_def, "the macro is defined here"); } BuiltinLintDiag::ElidedLifetimesInPaths(n, path_span, incl_angl_brckt, insertion_span) => { - add_elided_lifetime_in_path_suggestion( - sess.source_map(), - diag, - n, - path_span, - incl_angl_brckt, - insertion_span, + diag.subdiagnostic( + sess.dcx(), + elided_lifetime_in_path_suggestion( + sess.source_map(), + n, + path_span, + incl_angl_brckt, + insertion_span, + ), ); } BuiltinLintDiag::UnknownCrateTypes(span, note, sugg) => { diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index b0329702d1143..edfeacec7e3b7 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,4 @@ -use rustc_errors::{codes::*, Applicability, MultiSpan}; +use rustc_errors::{codes::*, Applicability, ElidedLifetimeInPathSubdiag, MultiSpan}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{ symbol::{Ident, Symbol}, @@ -907,6 +907,8 @@ pub(crate) struct ExplicitAnonymousLivetimeReportError { pub(crate) struct ImplicitElidedLifetimeNotAllowedHere { #[primary_span] pub(crate) span: Span, + #[subdiagnostic] + pub(crate) subdiag: ElidedLifetimeInPathSubdiag, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 753ba09d88686..c877ae5e21f48 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1883,20 +1883,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } | LifetimeRibKind::AnonymousWarn(_) => { - let mut err = - self.r.dcx().create_err(errors::ImplicitElidedLifetimeNotAllowedHere { - span: path_span, - }); let sess = self.r.tcx.sess; - rustc_errors::add_elided_lifetime_in_path_suggestion( + let subdiag = rustc_errors::elided_lifetime_in_path_suggestion( sess.source_map(), - &mut err, expected_lifetimes, path_span, !segment.has_generic_args, elided_lifetime_span, ); - err.emit(); + self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere { + span: path_span, + subdiag, + }); should_lint = false; for id in node_ids {