1
Fork 0

errors: only eagerly translate subdiagnostics

Subdiagnostics don't need to be lazily translated, they can always be
eagerly translated. Eager translation is slightly more complex as we need
to have a `DiagCtxt` available to perform the translation, which involves
slightly more threading of that context.

This slight increase in complexity should enable later simplifications -
like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages
into the diagnostic structs rather than having them in separate files
(working on that was what led to this change).

Signed-off-by: David Wood <david@davidtw.co>
This commit is contained in:
David Wood 2024-02-14 14:17:27 +00:00
parent bb89df6903
commit b80fc5d4e8
No known key found for this signature in database
43 changed files with 532 additions and 388 deletions

View file

@ -229,7 +229,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
seen_spans.insert(move_span);
}
use_spans.var_path_only_subdiag(&mut err, desired_action);
use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);
if !is_loop_move {
err.span_label(
@ -291,18 +291,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if needs_note {
if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span;
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move,
ty,
place: &note_msg,
span,
});
err.subdiagnostic(
self.dcx(),
crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move,
ty,
place: &note_msg,
span,
},
);
} else {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
is_partial_move,
ty,
place: &note_msg,
});
err.subdiagnostic(
self.dcx(),
crate::session_diagnostics::TypeNoCopy::Note {
is_partial_move,
ty,
place: &note_msg,
},
);
};
}
@ -557,7 +563,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
E0381,
"{used} binding {desc}{isnt_initialized}"
);
use_spans.var_path_only_subdiag(&mut err, desired_action);
use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action);
if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action
@ -848,9 +854,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&value_msg,
);
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
borrow_spans.var_path_only_subdiag(
self.dcx(),
&mut err,
crate::InitializationRequiringAction::Borrow,
);
move_spans.var_subdiag(None, &mut err, None, |kind, var_span| {
move_spans.var_subdiag(self.dcx(), &mut err, None, |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span },
@ -895,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_span,
&self.describe_any_place(borrow.borrowed_place.as_ref()),
);
borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| {
borrow_spans.var_subdiag(self.dcx(), &mut err, Some(borrow.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
let place = &borrow.borrowed_place;
let desc_place = self.describe_any_place(place.as_ref());
@ -1043,7 +1053,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"mutably borrow",
);
borrow_spans.var_subdiag(
None,
self.dcx(),
&mut err,
Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|kind, var_span| {
@ -1131,22 +1141,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
};
if issued_spans == borrow_spans {
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
place: desc_place,
var_span,
is_single_var: false,
},
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
borrow_spans.var_subdiag(
self.dcx(),
&mut err,
Some(gen_borrow_kind),
|kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
place: desc_place,
var_span,
is_single_var: false,
},
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
BorrowUsePlaceClosure {
place: desc_place,
var_span,
is_single_var: false,
}
}
}
}
});
},
);
} else {
issued_spans.var_subdiag(
Some(self.dcx()),
self.dcx(),
&mut err,
Some(issued_borrow.kind),
|kind, var_span| {
@ -1165,7 +1184,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
borrow_spans.var_subdiag(
Some(self.dcx()),
self.dcx(),
&mut err,
Some(gen_borrow_kind),
|kind, var_span| {
@ -2217,7 +2236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{name}` dropped here while still borrowed"));
borrow_spans.args_subdiag(&mut err, |args_span| {
borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_coroutine(),
args_span,
@ -2476,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None,
);
borrow_spans.args_subdiag(&mut err, |args_span| {
borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_coroutine(),
args_span,
@ -2935,7 +2954,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"assign",
);
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },
@ -2953,7 +2972,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| {
loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| {
use crate::session_diagnostics::CaptureVarCause::*;
match kind {
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span },

View file

@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic(
diag.subdiagnostic(
self.dcx(),
OnClosureNote::InvokedTwice {
place_name: &ty::place_to_string_for_capture(
@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic(
diag.subdiagnostic(
self.dcx(),
OnClosureNote::MovedTwice {
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place),
@ -587,11 +587,12 @@ impl UseSpans<'_> {
/// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_subdiag(
self,
dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic,
f: impl FnOnce(Span) -> CaptureArgLabel,
) {
if let UseSpans::ClosureUse { args_span, .. } = self {
err.subdiagnostic(f(args_span));
err.subdiagnostic(dcx, f(args_span));
}
}
@ -599,6 +600,7 @@ impl UseSpans<'_> {
/// only adds label to the `path_span`
pub(super) fn var_path_only_subdiag(
self,
dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic,
action: crate::InitializationRequiringAction,
) {
@ -607,20 +609,26 @@ impl UseSpans<'_> {
if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
match closure_kind {
hir::ClosureKind::Coroutine(_) => {
err.subdiagnostic(match action {
Borrow => BorrowInCoroutine { path_span },
MatchOn | Use => UseInCoroutine { path_span },
Assignment => AssignInCoroutine { path_span },
PartialAssignment => AssignPartInCoroutine { path_span },
});
err.subdiagnostic(
dcx,
match action {
Borrow => BorrowInCoroutine { path_span },
MatchOn | Use => UseInCoroutine { path_span },
Assignment => AssignInCoroutine { path_span },
PartialAssignment => AssignPartInCoroutine { path_span },
},
);
}
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
err.subdiagnostic(match action {
Borrow => BorrowInClosure { path_span },
MatchOn | Use => UseInClosure { path_span },
Assignment => AssignInClosure { path_span },
PartialAssignment => AssignPartInClosure { path_span },
});
err.subdiagnostic(
dcx,
match action {
Borrow => BorrowInClosure { path_span },
MatchOn | Use => UseInClosure { path_span },
Assignment => AssignInClosure { path_span },
PartialAssignment => AssignPartInClosure { path_span },
},
);
}
}
}
@ -629,32 +637,32 @@ impl UseSpans<'_> {
/// Add a subdiagnostic to the use of the captured variable, if it exists.
pub(super) fn var_subdiag(
self,
dcx: Option<&rustc_errors::DiagCtxt>,
dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic,
kind: Option<rustc_middle::mir::BorrowKind>,
f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause,
) {
if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self {
if capture_kind_span != path_span {
err.subdiagnostic(match kind {
Some(kd) => match kd {
rustc_middle::mir::BorrowKind::Shared
| rustc_middle::mir::BorrowKind::Fake => {
CaptureVarKind::Immut { kind_span: capture_kind_span }
}
err.subdiagnostic(
dcx,
match kind {
Some(kd) => match kd {
rustc_middle::mir::BorrowKind::Shared
| rustc_middle::mir::BorrowKind::Fake => {
CaptureVarKind::Immut { kind_span: capture_kind_span }
}
rustc_middle::mir::BorrowKind::Mut { .. } => {
CaptureVarKind::Mut { kind_span: capture_kind_span }
}
rustc_middle::mir::BorrowKind::Mut { .. } => {
CaptureVarKind::Mut { kind_span: capture_kind_span }
}
},
None => CaptureVarKind::Move { kind_span: capture_kind_span },
},
None => CaptureVarKind::Move { kind_span: capture_kind_span },
});
);
};
let diag = f(closure_kind, path_span);
match dcx {
Some(hd) => err.eager_subdiagnostic(hd, diag),
None => err.subdiagnostic(diag),
};
err.subdiagnostic(dcx, diag);
}
}
@ -1025,26 +1033,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{
err.subdiagnostic(CaptureReasonLabel::Call {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::Call {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
},
);
err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span });
}
CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap();
err.subdiagnostic(CaptureReasonLabel::OperatorUse {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::OperatorUse {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
},
);
if self.fn_self_span_reported.insert(fn_span) {
err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator {
span: self_arg.span,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonNote::LhsMoveByOperator { span: self_arg.span },
);
}
}
CallKind::Normal { self_arg, desugaring, method_did, method_args } => {
@ -1061,11 +1076,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
let func = tcx.def_path_str(method_did);
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf {
func,
place_name: place_name.clone(),
span: self_arg.span,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonNote::FuncTakeSelf {
func,
place_name: place_name.clone(),
span: self_arg.span,
},
);
}
let parent_did = tcx.parent(method_did);
let parent_self_ty =
@ -1079,7 +1097,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
});
if is_option_or_result && maybe_reinitialized_locations_is_empty {
err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span });
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::BorrowContent { var_span },
);
}
if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, tcx).ty;
@ -1093,18 +1114,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => false,
};
if suggest {
err.subdiagnostic(CaptureReasonSuggest::IterateSlice {
ty,
span: move_span.shrink_to_lo(),
});
err.subdiagnostic(
self.dcx(),
CaptureReasonSuggest::IterateSlice {
ty,
span: move_span.shrink_to_lo(),
},
);
}
err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::ImplicitCall {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
},
);
// If the moved place was a `&mut` ref, then we can
// suggest to reborrow it where it was moved, so it
// will still be valid by the time we get to the usage.
@ -1128,19 +1155,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
} else {
if let Some((CallDesugaringKind::Await, _)) = desugaring {
err.subdiagnostic(CaptureReasonLabel::Await {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::Await {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
},
);
} else {
err.subdiagnostic(CaptureReasonLabel::MethodCall {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::MethodCall {
fn_call_span,
place_name: &place_name,
is_partial,
is_loop_message,
},
);
}
// Erase and shadow everything that could be passed to the new infcx.
let ty = moved_place.ty(self.body, tcx).ty;
@ -1155,7 +1188,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
)
&& self.infcx.can_eq(self.param_env, ty, self_ty)
{
err.eager_subdiagnostic(
err.subdiagnostic(
self.dcx(),
CaptureReasonSuggest::FreshReborrow {
span: move_span.shrink_to_hi(),
@ -1239,17 +1272,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
} else {
if move_span != span || is_loop_message {
err.subdiagnostic(CaptureReasonLabel::MovedHere {
move_span,
is_partial,
is_move_msg,
is_loop_message,
});
err.subdiagnostic(
self.dcx(),
CaptureReasonLabel::MovedHere {
move_span,
is_partial,
is_move_msg,
is_loop_message,
},
);
}
// If the move error occurs due to a loop, don't show
// another message for the same span
if !is_loop_message {
move_spans.var_subdiag(None, err, None, |kind, var_span| match kind {
move_spans.var_subdiag(self.dcx(), err, None, |kind, var_span| match kind {
hir::ClosureKind::Coroutine(_) => {
CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial }
}

View file

@ -448,12 +448,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
None => "value".to_string(),
};
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
});
err.subdiagnostic(
self.dcx(),
crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
},
);
} else {
binds_to.sort();
binds_to.dedup();
@ -475,14 +478,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
Some(desc) => format!("`{desc}`"),
None => "value".to_string(),
};
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
});
err.subdiagnostic(
self.dcx(),
crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: place_ty,
place: &place_desc,
span,
},
);
use_spans.args_subdiag(err, |args_span| {
use_spans.args_subdiag(self.dcx(), err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::MoveOutPlace {
place: place_desc,
args_span,
@ -580,12 +586,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if binds_to.len() == 1 {
let place_desc = &format!("`{}`", self.local_names[*local].unwrap());
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: bind_to.ty,
place: place_desc,
span: binding_span,
});
err.subdiagnostic(
self.dcx(),
crate::session_diagnostics::TypeNoCopy::Label {
is_partial_move: false,
ty: bind_to.ty,
place: place_desc,
span: binding_span,
},
);
}
}

View file

@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
if suggest {
borrow_spans.var_subdiag(
None,
self.dcx(),
&mut err,
Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|_kind, var_span| {

View file

@ -616,13 +616,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
let upvar_span = upvars_map.get(&def_hir).unwrap().span;
diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span });
diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span });
diag.subdiagnostic(self.dcx(), VarHereDenote::Defined { span: upvar_def_span });
diag.subdiagnostic(self.dcx(), VarHereDenote::Captured { span: upvar_span });
}
}
if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() {
diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span });
diag.subdiagnostic(self.dcx(), VarHereDenote::FnMutInferred { span: fr_span });
}
self.suggest_move_on_borrowing_closure(&mut diag);
@ -788,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
},
};
diag.subdiagnostic(err_category);
diag.subdiagnostic(self.dcx(), err_category);
self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
@ -979,7 +979,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
ident.span,
"calling this method introduces the `impl`'s `'static` requirement",
);
err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span });
err.subdiagnostic(self.dcx(), RequireStaticErr::UsedImpl { multi_span });
err.span_suggestion_verbose(
span.shrink_to_hi(),
"consider relaxing the implicit `'static` requirement",