diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index dd9590016b990..61c5676b4053a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use rustc_errors::{ Applicability, Diagnostic, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, }; @@ -19,6 +22,7 @@ use rustc_span::symbol::{kw, Symbol}; use rustc_span::{sym, BytePos, Span}; use crate::diagnostics::BorrowedContentSource; +use crate::session_diagnostics::{FnMutBumpFn, ShowMutatingUpvar}; use crate::MirBorrowckCtxt; use rustc_const_eval::util::collect_writes::FindAssignments; @@ -864,14 +868,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { bug!("not an upvar") }; - err.span_label( - *span, - format!( - "calling `{}` requires mutable binding due to {}", - self.describe_place(the_place_err).unwrap(), - reason - ), - ); + let place = self.describe_place(the_place_err).unwrap(); + let sub_label = ShowMutatingUpvar::RequireMutableBinding { place, reason, span: *span }; + err.subdiagnostic(sub_label); } } @@ -972,7 +971,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut Diagnostic, sp: Span, act: &str) { - err.span_label(sp, format!("cannot {act}")); + err.subdiagnostic(FnMutBumpFn::Cannot { act, sp }); let hir = self.infcx.tcx.hir(); let closure_id = self.mir_hir_id(); @@ -1025,9 +1024,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { _ => None, }; if let Some(span) = arg { - err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); - err.span_label(func.span, "expects `Fn` instead of `FnMut`"); - err.span_label(self.body.span, "in this closure"); + err.subdiagnostic(FnMutBumpFn::AcceptFnMut { span }); + err.subdiagnostic(FnMutBumpFn::AcceptFn { span: func.span }); + err.subdiagnostic(FnMutBumpFn::Here { span: self.body.span }); look_at_return = false; } } @@ -1048,12 +1047,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { kind: hir::ImplItemKind::Fn(sig, _), .. }) => { - err.span_label(ident.span, ""); - err.span_label( - sig.decl.output.span(), - "change this to return `FnMut` instead of `Fn`", - ); - err.span_label(self.body.span, "in this closure"); + err.subdiagnostic(FnMutBumpFn::EmptyLabel { span: ident.span }); + err.subdiagnostic(FnMutBumpFn::ReturnFnMut { span: sig.decl.output.span() }); + err.subdiagnostic(FnMutBumpFn::Here { span: self.body.span }); } _ => {} } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 5d750c6ca8c7b..a63bbfa32a1f8 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -157,3 +157,49 @@ pub(crate) enum RequireStaticErr { multi_span: MultiSpan, }, } + +#[derive(SessionSubdiagnostic)] +pub(crate) enum ShowMutatingUpvar { + #[label(borrowck::require_mutable_binding)] + RequireMutableBinding { + place: String, + reason: String, + #[primary_span] + span: Span, + }, +} + +#[derive(SessionSubdiagnostic)] +pub(crate) enum FnMutBumpFn<'a> { + #[label(borrowck::cannot_act)] + Cannot { + act: &'a str, + #[primary_span] + sp: Span, + }, + #[label(borrowck::expects_fnmut_not_fn)] + AcceptFnMut { + #[primary_span] + span: Span, + }, + #[label(borrowck::expects_fn_not_fnmut)] + AcceptFn { + #[primary_span] + span: Span, + }, + #[label(borrowck::empty_label)] + EmptyLabel { + #[primary_span] + span: Span, + }, + #[label(borrowck::in_this_closure)] + Here { + #[primary_span] + span: Span, + }, + #[label(borrowck::return_fnmut)] + ReturnFnMut { + #[primary_span] + span: Span, + }, +} diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 67f2156f32e50..3ef282daffb13 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -58,3 +58,23 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement + +borrowck_require_mutable_binding = + calling `{$place}` requires mutable binding due to {$reason} + +borrowck_cannot_act = + cannot {$act} + +borrowck_expects_fnmut_not_fn = + change this to accept `FnMut` instead of `Fn` + +borrowck_expects_fn_not_fnmut = + expects `Fn` instead of `FnMut` + +borrowck_empty_label = {""} + +borrowck_in_this_closure = + in this closure + +borrowck_return_fnmut = + change this to return `FnMut` instead of `Fn`