mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
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:
parent
bb89df6903
commit
b80fc5d4e8
@ -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 {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_msg,
|
||||
span,
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
crate::session_diagnostics::TypeNoCopy::Note {
|
||||
is_partial_move,
|
||||
ty,
|
||||
place: ¬e_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,7 +1141,11 @@ 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| {
|
||||
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 {
|
||||
@ -1140,13 +1154,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
is_single_var: false,
|
||||
},
|
||||
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
|
||||
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false }
|
||||
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 },
|
||||
|
@ -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 {
|
||||
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 {
|
||||
err.subdiagnostic(
|
||||
dcx,
|
||||
match action {
|
||||
Borrow => BorrowInClosure { path_span },
|
||||
MatchOn | Use => UseInClosure { path_span },
|
||||
Assignment => AssignInClosure { path_span },
|
||||
PartialAssignment => AssignPartInClosure { path_span },
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -629,14 +637,16 @@ 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 {
|
||||
err.subdiagnostic(
|
||||
dcx,
|
||||
match kind {
|
||||
Some(kd) => match kd {
|
||||
rustc_middle::mir::BorrowKind::Shared
|
||||
| rustc_middle::mir::BorrowKind::Fake => {
|
||||
@ -648,13 +658,11 @@ impl UseSpans<'_> {
|
||||
}
|
||||
},
|
||||
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 {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
CaptureReasonLabel::Call {
|
||||
fn_call_span,
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span });
|
||||
},
|
||||
);
|
||||
err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span });
|
||||
}
|
||||
CallKind::Operator { self_arg, .. } => {
|
||||
let self_arg = self_arg.unwrap();
|
||||
err.subdiagnostic(CaptureReasonLabel::OperatorUse {
|
||||
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 {
|
||||
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 {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
CaptureReasonSuggest::IterateSlice {
|
||||
ty,
|
||||
span: move_span.shrink_to_lo(),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
err.subdiagnostic(CaptureReasonLabel::ImplicitCall {
|
||||
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 {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
CaptureReasonLabel::Await {
|
||||
fn_call_span,
|
||||
place_name: &place_name,
|
||||
is_partial,
|
||||
is_loop_message,
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
err.subdiagnostic(CaptureReasonLabel::MethodCall {
|
||||
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 {
|
||||
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 }
|
||||
}
|
||||
|
@ -448,12 +448,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
None => "value".to_string(),
|
||||
};
|
||||
|
||||
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label {
|
||||
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 {
|
||||
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 {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
crate::session_diagnostics::TypeNoCopy::Label {
|
||||
is_partial_move: false,
|
||||
ty: bind_to.ty,
|
||||
place: place_desc,
|
||||
span: binding_span,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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| {
|
||||
|
@ -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",
|
||||
|
@ -122,7 +122,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
|
||||
diag.span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
diag.subdiagnostic(dcx, missing_features);
|
||||
}
|
||||
diag.arg("features", self.features.join(", "));
|
||||
diag
|
||||
|
@ -131,7 +131,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
|
||||
diag.span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
diag.subdiagnostic(dcx, missing_features);
|
||||
}
|
||||
diag.arg("features", self.features.join(", "));
|
||||
diag
|
||||
|
@ -131,7 +131,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
||||
// FIXME(effects) revisit this
|
||||
if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
|
||||
let span = tcx.def_span(data.impl_def_id);
|
||||
err.subdiagnostic(errors::NonConstImplNote { span });
|
||||
err.subdiagnostic(tcx.dcx(), errors::NonConstImplNote { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage {
|
||||
/// Translatable message which has already been translated eagerly.
|
||||
///
|
||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||
/// be instantiated multiple times with different values. As translation normally happens
|
||||
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
|
||||
/// the setting of diagnostic arguments in the derived code will overwrite previous variable
|
||||
/// values and only the final value will be set when translation occurs - resulting in
|
||||
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||
/// stores messages which have been translated eagerly.
|
||||
Eager(Cow<'static, str>),
|
||||
/// be instantiated multiple times with different values. These subdiagnostics' messages
|
||||
/// are translated when they are added to the parent diagnostic, producing this variant of
|
||||
/// `DiagnosticMessage`.
|
||||
Translated(Cow<'static, str>),
|
||||
/// Identifier of a Fluent message. Instances of this variant are generated by the
|
||||
/// `Subdiagnostic` derive.
|
||||
FluentIdentifier(FluentId),
|
||||
@ -307,19 +303,15 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
|
||||
pub enum DiagnosticMessage {
|
||||
/// Non-translatable diagnostic message.
|
||||
Str(Cow<'static, str>),
|
||||
/// Translatable message which has already been translated eagerly.
|
||||
/// Translatable message which has been already translated.
|
||||
///
|
||||
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
|
||||
/// be instantiated multiple times with different values. As translation normally happens
|
||||
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run,
|
||||
/// the setting of diagnostic arguments in the derived code will overwrite previous variable
|
||||
/// values and only the final value will be set when translation occurs - resulting in
|
||||
/// incorrect diagnostics. Eager translation results in translation for a subdiagnostic
|
||||
/// happening immediately after the subdiagnostic derive's logic has been run. This variant
|
||||
/// stores messages which have been translated eagerly.
|
||||
Eager(Cow<'static, str>),
|
||||
/// be instantiated multiple times with different values. These subdiagnostics' messages
|
||||
/// are translated when they are added to the parent diagnostic, producing this variant of
|
||||
/// `DiagnosticMessage`.
|
||||
Translated(Cow<'static, str>),
|
||||
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic
|
||||
/// message.
|
||||
/// message. Yet to be translated.
|
||||
///
|
||||
/// <https://projectfluent.org/fluent/guide/hello.html>
|
||||
/// <https://projectfluent.org/fluent/guide/attributes.html>
|
||||
@ -336,7 +328,7 @@ impl DiagnosticMessage {
|
||||
pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
|
||||
let attr = match sub {
|
||||
SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
|
||||
SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s),
|
||||
SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s),
|
||||
SubdiagnosticMessage::FluentIdentifier(id) => {
|
||||
return DiagnosticMessage::FluentIdentifier(id, None);
|
||||
}
|
||||
@ -345,7 +337,7 @@ impl DiagnosticMessage {
|
||||
|
||||
match self {
|
||||
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()),
|
||||
DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()),
|
||||
DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()),
|
||||
DiagnosticMessage::FluentIdentifier(id, _) => {
|
||||
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
|
||||
}
|
||||
@ -354,7 +346,7 @@ impl DiagnosticMessage {
|
||||
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match self {
|
||||
DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s),
|
||||
DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s),
|
||||
DiagnosticMessage::FluentIdentifier(_, _) => None,
|
||||
}
|
||||
}
|
||||
@ -396,7 +388,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage {
|
||||
fn into(self) -> SubdiagnosticMessage {
|
||||
match self {
|
||||
DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
|
||||
DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s),
|
||||
DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s),
|
||||
DiagnosticMessage::FluentIdentifier(id, None) => {
|
||||
SubdiagnosticMessage::FluentIdentifier(id)
|
||||
}
|
||||
|
@ -851,18 +851,11 @@ impl Diagnostic {
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
|
||||
/// [rustc_macros::Subdiagnostic]).
|
||||
pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self {
|
||||
subdiagnostic.add_to_diagnostic(self);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
|
||||
/// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages
|
||||
/// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
|
||||
/// interpolated variables).
|
||||
pub fn eager_subdiagnostic(
|
||||
pub fn subdiagnostic(
|
||||
&mut self,
|
||||
dcx: &crate::DiagCtxt,
|
||||
subdiagnostic: impl AddToDiagnostic,
|
||||
@ -921,7 +914,7 @@ impl Diagnostic {
|
||||
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by
|
||||
/// combining it with the primary message of the diagnostic (if translatable, otherwise it just
|
||||
/// passes the user's string along).
|
||||
fn subdiagnostic_message_to_diagnostic_message(
|
||||
pub(crate) fn subdiagnostic_message_to_diagnostic_message(
|
||||
&self,
|
||||
attr: impl Into<SubdiagnosticMessage>,
|
||||
) -> DiagnosticMessage {
|
||||
|
@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
|
||||
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
|
||||
));
|
||||
forward!((subdiagnostic, with_subdiagnostic)(
|
||||
subdiagnostic: impl crate::AddToDiagnostic,
|
||||
));
|
||||
forward!((eager_subdiagnostic, with_eager_subdiagnostic)(
|
||||
dcx: &DiagCtxt,
|
||||
subdiagnostic: impl crate::AddToDiagnostic,
|
||||
));
|
||||
|
@ -10,6 +10,7 @@
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{FileLines, FileName, SourceFile, Span};
|
||||
|
||||
use crate::error::TranslateError;
|
||||
use crate::snippet::{
|
||||
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
|
||||
};
|
||||
@ -559,6 +560,18 @@ pub struct SilentEmitter {
|
||||
pub fatal_note: String,
|
||||
}
|
||||
|
||||
pub fn silent_translate<'a>(
|
||||
message: &'a DiagnosticMessage,
|
||||
) -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
match message {
|
||||
DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)),
|
||||
DiagnosticMessage::FluentIdentifier(identifier, _) => {
|
||||
// Any value works here.
|
||||
Ok(identifier.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Translate for SilentEmitter {
|
||||
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
|
||||
None
|
||||
@ -567,6 +580,16 @@ impl Translate for SilentEmitter {
|
||||
fn fallback_fluent_bundle(&self) -> &FluentBundle {
|
||||
panic!("silent emitter attempted to translate message")
|
||||
}
|
||||
|
||||
// Override `translate_message` for the silent emitter because eager translation of
|
||||
// subdiagnostics result in a call to this.
|
||||
fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a DiagnosticMessage,
|
||||
_: &'a FluentArgs<'_>,
|
||||
) -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
silent_translate(message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
|
@ -640,7 +640,8 @@ impl DiagCtxt {
|
||||
message: DiagnosticMessage,
|
||||
args: impl Iterator<Item = DiagnosticArg<'a>>,
|
||||
) -> SubdiagnosticMessage {
|
||||
SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args)))
|
||||
let inner = self.inner.borrow();
|
||||
inner.eagerly_translate(message, args)
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `String`.
|
||||
@ -650,8 +651,7 @@ impl DiagCtxt {
|
||||
args: impl Iterator<Item = DiagnosticArg<'a>>,
|
||||
) -> String {
|
||||
let inner = self.inner.borrow();
|
||||
let args = crate::translation::to_fluent_args(args);
|
||||
inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
|
||||
inner.eagerly_translate_to_string(message, args)
|
||||
}
|
||||
|
||||
// This is here to not allow mutation of flags;
|
||||
@ -1446,6 +1446,25 @@ impl DiagCtxtInner {
|
||||
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied())
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`.
|
||||
pub fn eagerly_translate<'a>(
|
||||
&self,
|
||||
message: DiagnosticMessage,
|
||||
args: impl Iterator<Item = DiagnosticArg<'a>>,
|
||||
) -> SubdiagnosticMessage {
|
||||
SubdiagnosticMessage::Translated(Cow::from(self.eagerly_translate_to_string(message, args)))
|
||||
}
|
||||
|
||||
/// Translate `message` eagerly with `args` to `String`.
|
||||
pub fn eagerly_translate_to_string<'a>(
|
||||
&self,
|
||||
message: DiagnosticMessage,
|
||||
args: impl Iterator<Item = DiagnosticArg<'a>>,
|
||||
) -> String {
|
||||
let args = crate::translation::to_fluent_args(args);
|
||||
self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
|
||||
}
|
||||
|
||||
fn flush_delayed(&mut self) {
|
||||
if self.delayed_bugs.is_empty() {
|
||||
return;
|
||||
@ -1484,15 +1503,22 @@ impl DiagCtxtInner {
|
||||
}
|
||||
|
||||
let mut bug =
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner };
|
||||
if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner };
|
||||
|
||||
// "Undelay" the delayed bugs (into plain `Bug`s).
|
||||
if bug.level != DelayedBug {
|
||||
// NOTE(eddyb) not panicking here because we're already producing
|
||||
// an ICE, and the more information the merrier.
|
||||
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel {
|
||||
let subdiag = InvalidFlushedDelayedDiagnosticLevel {
|
||||
span: bug.span.primary_span().unwrap(),
|
||||
level: bug.level,
|
||||
};
|
||||
// FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
|
||||
// just uses `DiagCtxtInner` functions.
|
||||
subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| {
|
||||
let args = diag.args();
|
||||
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||
self.eagerly_translate(msg, args)
|
||||
});
|
||||
}
|
||||
bug.level = Bug;
|
||||
@ -1527,25 +1553,35 @@ impl DelayedDiagnostic {
|
||||
DelayedDiagnostic { inner: diagnostic, note: backtrace }
|
||||
}
|
||||
|
||||
fn decorate(mut self) -> Diagnostic {
|
||||
fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic {
|
||||
// FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it
|
||||
// just uses `DiagCtxtInner` functions.
|
||||
let subdiag_with = |diag: &mut Diagnostic, msg| {
|
||||
let args = diag.args();
|
||||
let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
|
||||
dcx.eagerly_translate(msg, args)
|
||||
};
|
||||
|
||||
match self.note.status() {
|
||||
BacktraceStatus::Captured => {
|
||||
let inner = &self.inner;
|
||||
self.inner.subdiagnostic(DelayedAtWithNewline {
|
||||
let subdiag = DelayedAtWithNewline {
|
||||
span: inner.span.primary_span().unwrap_or(DUMMY_SP),
|
||||
emitted_at: inner.emitted_at.clone(),
|
||||
note: self.note,
|
||||
});
|
||||
};
|
||||
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
|
||||
}
|
||||
// Avoid the needless newline when no backtrace has been captured,
|
||||
// the display impl should just be a single line.
|
||||
_ => {
|
||||
let inner = &self.inner;
|
||||
self.inner.subdiagnostic(DelayedAtWithoutNewline {
|
||||
let subdiag = DelayedAtWithoutNewline {
|
||||
span: inner.span.primary_span().unwrap_or(DUMMY_SP),
|
||||
emitted_at: inner.emitted_at.clone(),
|
||||
note: self.note,
|
||||
});
|
||||
};
|
||||
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1691,15 +1727,15 @@ 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 add_elided_lifetime_in_path_suggestion<E: EmissionGuarantee>(
|
||||
source_map: &SourceMap,
|
||||
diag: &mut Diagnostic,
|
||||
diag: &mut DiagnosticBuilder<'_, E>,
|
||||
n: usize,
|
||||
path_span: Span,
|
||||
incl_angl_brckt: bool,
|
||||
insertion_span: Span,
|
||||
) {
|
||||
diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n });
|
||||
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;
|
||||
@ -1708,11 +1744,10 @@ pub fn add_elided_lifetime_in_path_suggestion(
|
||||
let suggestion =
|
||||
if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
|
||||
|
||||
diag.subdiagnostic(IndicateAnonymousLifetime {
|
||||
span: insertion_span.shrink_to_hi(),
|
||||
count: n,
|
||||
suggestion,
|
||||
});
|
||||
diag.subdiagnostic(
|
||||
diag.dcx,
|
||||
IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
|
||||
);
|
||||
}
|
||||
|
||||
pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(
|
||||
|
@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
|
||||
use crate::snippet::Style;
|
||||
use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_error_messages::FluentArgs;
|
||||
pub use rustc_error_messages::FluentArgs;
|
||||
use std::borrow::Cow;
|
||||
use std::env;
|
||||
use std::error::Report;
|
||||
@ -61,7 +61,7 @@ pub trait Translate {
|
||||
) -> Result<Cow<'_, str>, TranslateError<'_>> {
|
||||
trace!(?message, ?args);
|
||||
let (identifier, attr) = match message {
|
||||
DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => {
|
||||
DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => {
|
||||
return Ok(Cow::Borrowed(msg));
|
||||
}
|
||||
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),
|
||||
|
@ -7,7 +7,7 @@ use crate::mbe::{
|
||||
use rustc_ast::token::{self, Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
|
||||
use rustc_errors::{Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage};
|
||||
use rustc_parse::parser::{Parser, Recovery};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::Ident;
|
||||
@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>(
|
||||
err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro");
|
||||
}
|
||||
|
||||
annotate_doc_comment(&mut err, sess.source_map(), span);
|
||||
annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span);
|
||||
|
||||
if let Some(span) = remaining_matcher.span() {
|
||||
err.span_note(span, format!("while trying to match {remaining_matcher}"));
|
||||
@ -311,12 +311,17 @@ enum ExplainDocComment {
|
||||
},
|
||||
}
|
||||
|
||||
pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) {
|
||||
pub(super) fn annotate_doc_comment(
|
||||
dcx: &DiagCtxt,
|
||||
err: &mut Diagnostic,
|
||||
sm: &SourceMap,
|
||||
span: Span,
|
||||
) {
|
||||
if let Ok(src) = sm.span_to_snippet(span) {
|
||||
if src.starts_with("///") || src.starts_with("/**") {
|
||||
err.subdiagnostic(ExplainDocComment::Outer { span });
|
||||
err.subdiagnostic(dcx, ExplainDocComment::Outer { span });
|
||||
} else if src.starts_with("//!") || src.starts_with("/*!") {
|
||||
err.subdiagnostic(ExplainDocComment::Inner { span });
|
||||
err.subdiagnostic(dcx, ExplainDocComment::Inner { span });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -454,7 +454,7 @@ pub fn compile_declarative_macro(
|
||||
let sp = token.span.substitute_dummy(def.span);
|
||||
let mut err = sess.dcx().struct_span_err(sp, s);
|
||||
err.span_label(sp, msg);
|
||||
annotate_doc_comment(&mut err, sess.source_map(), sp);
|
||||
annotate_doc_comment(sess.dcx(), &mut err, sess.source_map(), sp);
|
||||
err.emit();
|
||||
return dummy_syn_ext();
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|
||||
let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi());
|
||||
let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi };
|
||||
diag.subdiagnostic(sugg);
|
||||
diag.subdiagnostic(self.dcx(), sugg);
|
||||
}
|
||||
|
||||
/// When the previously checked expression (the scrutinee) diverges,
|
||||
|
@ -993,19 +993,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||
if let Some((deref_ty, _)) = derefed {
|
||||
// Give a note about what the expr derefs to.
|
||||
if deref_ty != self.expr_ty.peel_refs() {
|
||||
err.subdiagnostic(errors::DerefImplsIsEmpty {
|
||||
err.subdiagnostic(
|
||||
fcx.dcx(),
|
||||
errors::DerefImplsIsEmpty {
|
||||
span: self.expr_span,
|
||||
deref_ty: fcx.ty_to_string(deref_ty),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Create a multipart suggestion: add `!` and `.is_empty()` in
|
||||
// place of the cast.
|
||||
err.subdiagnostic(errors::UseIsEmpty {
|
||||
err.subdiagnostic(
|
||||
fcx.dcx(),
|
||||
errors::UseIsEmpty {
|
||||
lo: self.expr_span.shrink_to_lo(),
|
||||
hi: self.span.with_lo(self.expr_span.hi()),
|
||||
expr_ty: fcx.ty_to_string(self.expr_ty),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if let Some(sp) =
|
||||
tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
|
||||
{
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
}
|
||||
oprnd_t = Ty::new_error(tcx, err.emit());
|
||||
}
|
||||
@ -2050,7 +2050,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
.shrink_to_hi()
|
||||
.to(range_end.span);
|
||||
|
||||
err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr });
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1269,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
{
|
||||
// The user provided `ptr::null()`, but the function expects
|
||||
// `ptr::null_mut()`.
|
||||
err.subdiagnostic(SuggestPtrNullMut { span: arg.span });
|
||||
err.subdiagnostic(self.dcx(), SuggestPtrNullMut { span: arg.span });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -458,13 +458,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// but those checks need to be a bit more delicate and the benefit is diminishing.
|
||||
if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
|
||||
let sugg = prefix_wrap(".as_ref()");
|
||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::SuggestConvertViaMethod {
|
||||
span: expr.span.shrink_to_hi(),
|
||||
sugg,
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} else if let Some((deref_ty, _)) =
|
||||
self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1)
|
||||
@ -472,13 +475,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& error_tys_equate_as_ref
|
||||
{
|
||||
let sugg = prefix_wrap(".as_deref()");
|
||||
err.subdiagnostic(errors::SuggestConvertViaMethod {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::SuggestConvertViaMethod {
|
||||
span: expr.span.shrink_to_hi(),
|
||||
sugg,
|
||||
expected,
|
||||
found,
|
||||
borrow_removal_span,
|
||||
});
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
|
||||
&& Some(adt.did()) == self.tcx.lang_items().string()
|
||||
@ -565,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
end: span.shrink_to_hi(),
|
||||
},
|
||||
};
|
||||
err.subdiagnostic(suggest_boxing);
|
||||
err.subdiagnostic(self.dcx(), suggest_boxing);
|
||||
|
||||
true
|
||||
} else {
|
||||
@ -799,29 +805,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
match &fn_decl.output {
|
||||
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => {
|
||||
// `fn main()` must return `()`, do not suggest changing return type
|
||||
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span });
|
||||
err.subdiagnostic(self.dcx(), errors::ExpectedReturnTypeLabel::Unit { span });
|
||||
return true;
|
||||
}
|
||||
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
|
||||
if let Some(found) = found.make_suggestable(self.tcx, false) {
|
||||
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
|
||||
span,
|
||||
found: found.to_string(),
|
||||
});
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() },
|
||||
);
|
||||
return true;
|
||||
} else if let ty::Closure(_, args) = found.kind()
|
||||
// FIXME(compiler-errors): Get better at printing binders...
|
||||
&& let closure = args.as_closure()
|
||||
&& closure.sig().is_suggestable(self.tcx, false)
|
||||
{
|
||||
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::AddReturnTypeSuggestion::Add {
|
||||
span,
|
||||
found: closure.print_as_impl_trait().to_string(),
|
||||
});
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
// FIXME: if `found` could be `impl Iterator` we should suggest that.
|
||||
err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span });
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::AddReturnTypeSuggestion::MissingHere { span },
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -843,16 +855,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
debug!(?found);
|
||||
if found.is_suggestable(self.tcx, false) {
|
||||
if term.span.is_empty() {
|
||||
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::AddReturnTypeSuggestion::Add {
|
||||
span: term.span,
|
||||
found: found.to_string(),
|
||||
});
|
||||
},
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::ExpectedReturnTypeLabel::Other {
|
||||
span: term.span,
|
||||
expected,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -867,10 +885,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let ty = self.normalize(hir_ty.span, ty);
|
||||
let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
|
||||
if self.can_coerce(expected, ty) {
|
||||
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other {
|
||||
span: hir_ty.span,
|
||||
expected,
|
||||
});
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
|
||||
);
|
||||
self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
|
||||
return true;
|
||||
}
|
||||
@ -1106,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None);
|
||||
if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) {
|
||||
// `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -1220,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
} else {
|
||||
return false;
|
||||
};
|
||||
diag.subdiagnostic(subdiag);
|
||||
diag.subdiagnostic(self.dcx(), subdiag);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -3173,7 +3173,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
if impls_trait(trait_info.def_id) {
|
||||
self.suggest_valid_traits(err, vec![trait_info.def_id], false);
|
||||
} else {
|
||||
err.subdiagnostic(CandidateTraitNote {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
CandidateTraitNote {
|
||||
span: self.tcx.def_span(trait_info.def_id),
|
||||
trait_name: self.tcx.def_path_str(trait_info.def_id),
|
||||
item_name,
|
||||
@ -3185,7 +3187,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
ToString::to_string,
|
||||
)
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
trait_infos => {
|
||||
|
@ -824,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// If the previous expression was a block expression, suggest parentheses
|
||||
// (turning this into a binary subtraction operation instead.)
|
||||
// for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs)
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
} else {
|
||||
match actual.kind() {
|
||||
Uint(_) if op == hir::UnOp::Neg => {
|
||||
|
@ -846,7 +846,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
arm_ty,
|
||||
arm_span,
|
||||
) {
|
||||
err.subdiagnostic(subdiag);
|
||||
err.subdiagnostic(self.dcx(), subdiag);
|
||||
}
|
||||
if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id)
|
||||
&& let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id)
|
||||
@ -892,7 +892,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
else_ty,
|
||||
else_span,
|
||||
) {
|
||||
err.subdiagnostic(subdiag);
|
||||
err.subdiagnostic(self.dcx(), subdiag);
|
||||
}
|
||||
// don't suggest wrapping either blocks in `if .. {} else {}`
|
||||
let is_empty_arm = |id| {
|
||||
|
@ -342,7 +342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
trait_predicates: trait_predicates.join(", "),
|
||||
}
|
||||
};
|
||||
err.subdiagnostic(suggestion);
|
||||
err.subdiagnostic(self.dcx(), suggestion);
|
||||
}
|
||||
|
||||
pub(super) fn report_placeholder_failure(
|
||||
|
@ -84,7 +84,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
|
||||
end_sp: return_sp.shrink_to_hi(),
|
||||
};
|
||||
err.subdiagnostic(sugg);
|
||||
err.subdiagnostic(self.dcx(), sugg);
|
||||
|
||||
let mut starts = Vec::new();
|
||||
let mut ends = Vec::new();
|
||||
@ -93,7 +93,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
ends.push(span.shrink_to_hi());
|
||||
}
|
||||
let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
|
||||
err.subdiagnostic(sugg);
|
||||
err.subdiagnostic(self.dcx(), sugg);
|
||||
}
|
||||
|
||||
pub(super) fn suggest_tuple_pattern(
|
||||
@ -138,7 +138,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
span_low: cause.span.shrink_to_lo(),
|
||||
span_high: cause.span.shrink_to_hi(),
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
diag.subdiagnostic(self.dcx(), sugg);
|
||||
}
|
||||
_ => {
|
||||
// More than one matching variant.
|
||||
@ -147,7 +147,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
cause_span: cause.span,
|
||||
compatible_variants,
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
diag.subdiagnostic(self.dcx(), sugg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -219,9 +219,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
},
|
||||
(_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
|
||||
// FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
|
||||
diag.subdiagnostic(ConsiderAddingAwait::FutureSugg {
|
||||
span: exp_span.shrink_to_hi(),
|
||||
});
|
||||
diag.subdiagnostic(
|
||||
self.dcx(),
|
||||
ConsiderAddingAwait::FutureSugg { span: exp_span.shrink_to_hi() },
|
||||
);
|
||||
Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
|
||||
}
|
||||
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
|
||||
@ -246,7 +247,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
_ => None,
|
||||
};
|
||||
if let Some(subdiag) = subdiag {
|
||||
diag.subdiagnostic(subdiag);
|
||||
diag.subdiagnostic(self.dcx(), subdiag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -282,7 +283,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
diag.subdiagnostic(suggestion);
|
||||
diag.subdiagnostic(self.dcx(), suggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,15 +323,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
(true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
|
||||
(false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
|
||||
(true, true) => {
|
||||
diag.subdiagnostic(FnItemsAreDistinct);
|
||||
diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
|
||||
FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
|
||||
}
|
||||
(false, false) => {
|
||||
diag.subdiagnostic(FnItemsAreDistinct);
|
||||
diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
|
||||
FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
|
||||
}
|
||||
};
|
||||
diag.subdiagnostic(sugg);
|
||||
diag.subdiagnostic(self.dcx(), sugg);
|
||||
}
|
||||
(ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
|
||||
let expected_sig =
|
||||
@ -339,7 +340,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
&(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2));
|
||||
|
||||
if self.same_type_modulo_infer(*expected_sig, *found_sig) {
|
||||
diag.subdiagnostic(FnUniqTypes);
|
||||
diag.subdiagnostic(self.dcx(), FnUniqTypes);
|
||||
}
|
||||
|
||||
if !self.same_type_modulo_infer(*found_sig, *expected_sig)
|
||||
@ -368,7 +369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
}
|
||||
};
|
||||
|
||||
diag.subdiagnostic(sug);
|
||||
diag.subdiagnostic(self.dcx(), sug);
|
||||
}
|
||||
(ty::FnDef(did, args), ty::FnPtr(sig)) => {
|
||||
let expected_sig =
|
||||
@ -387,7 +388,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
format!("{fn_name} as {found_sig}")
|
||||
};
|
||||
|
||||
diag.subdiagnostic(FnConsiderCasting { casting });
|
||||
diag.subdiagnostic(self.dcx(), FnConsiderCasting { casting });
|
||||
}
|
||||
_ => {
|
||||
return;
|
||||
@ -819,7 +820,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
let diag = self.consider_returning_binding_diag(blk, expected_ty);
|
||||
match diag {
|
||||
Some(diag) => {
|
||||
err.subdiagnostic(diag);
|
||||
err.subdiagnostic(self.dcx(), diag);
|
||||
true
|
||||
}
|
||||
None => false,
|
||||
|
@ -1758,7 +1758,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
|
||||
diag.note(note.to_string());
|
||||
}
|
||||
if let Some(sugg) = self.suggestion {
|
||||
diag.subdiagnostic(sugg);
|
||||
diag.subdiagnostic(diag.dcx, sugg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -331,44 +331,7 @@ impl DiagnosticDeriveVariantBuilder {
|
||||
}
|
||||
}
|
||||
(Meta::Path(_), "subdiagnostic") => {
|
||||
if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() {
|
||||
let DiagnosticDeriveKind::Diagnostic = self.kind else {
|
||||
// No eager translation for lints.
|
||||
return Ok(quote! { diag.subdiagnostic(#binding); });
|
||||
};
|
||||
return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); });
|
||||
} else {
|
||||
return Ok(quote! { diag.subdiagnostic(#binding); });
|
||||
}
|
||||
}
|
||||
(Meta::List(meta_list), "subdiagnostic") => {
|
||||
let err = || {
|
||||
span_err(
|
||||
meta_list.span().unwrap(),
|
||||
"`eager` is the only supported nested attribute for `subdiagnostic`",
|
||||
)
|
||||
.emit();
|
||||
};
|
||||
|
||||
let Ok(p): Result<Path, _> = meta_list.parse_args() else {
|
||||
err();
|
||||
return Ok(quote! {});
|
||||
};
|
||||
|
||||
if !p.is_ident("eager") {
|
||||
err();
|
||||
return Ok(quote! {});
|
||||
}
|
||||
|
||||
match &self.kind {
|
||||
DiagnosticDeriveKind::Diagnostic => {}
|
||||
DiagnosticDeriveKind::LintDiagnostic => {
|
||||
throw_invalid_attr!(attr, |diag| {
|
||||
diag.help("eager subdiagnostics are not supported on lints")
|
||||
})
|
||||
}
|
||||
};
|
||||
return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); });
|
||||
return Ok(quote! { diag.subdiagnostic(diag.dcx, #binding); });
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
@ -1109,7 +1109,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
|
||||
|
||||
let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some());
|
||||
if !is_empty_match && all_arms_have_guards {
|
||||
err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded);
|
||||
err.subdiagnostic(cx.tcx.dcx(), NonExhaustiveMatchAllArmsGuarded);
|
||||
}
|
||||
if let Some((span, sugg)) = suggestion {
|
||||
err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
|
||||
|
@ -270,7 +270,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
|
||||
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
|
||||
diag.span_label(self.yield_sp, fluent::_subdiag::label);
|
||||
if let Some(reason) = self.reason {
|
||||
diag.subdiagnostic(reason);
|
||||
diag.subdiagnostic(diag.dcx, reason);
|
||||
}
|
||||
diag.span_help(self.src_sp, fluent::_subdiag::help);
|
||||
diag.arg("pre", self.pre);
|
||||
|
@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> {
|
||||
let mut err = self.dcx().struct_span_err(span, msg);
|
||||
let sp = self.sess.source_map().start_point(self.token.span);
|
||||
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
}
|
||||
err.span_label(span, "expected expression");
|
||||
|
||||
|
@ -1433,7 +1433,7 @@ impl<'a> Parser<'a> {
|
||||
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
|
||||
// then suggest parens around the lhs.
|
||||
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) {
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
}
|
||||
err
|
||||
})
|
||||
|
@ -1917,7 +1917,7 @@ impl<'a> Parser<'a> {
|
||||
if self.token.kind == token::Not {
|
||||
if let Err(mut err) = self.unexpected::<FieldDef>() {
|
||||
// Encounter the macro invocation
|
||||
err.subdiagnostic(MacroExpandsToAdtField { adt_ty });
|
||||
err.subdiagnostic(self.dcx(), MacroExpandsToAdtField { adt_ty });
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
@ -2336,10 +2336,13 @@ impl<'a> Parser<'a> {
|
||||
.into_iter()
|
||||
.any(|s| self.prev_token.is_ident_named(s));
|
||||
|
||||
err.subdiagnostic(errors::FnTraitMissingParen {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
errors::FnTraitMissingParen {
|
||||
span: self.prev_token.span,
|
||||
machine_applicable,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
|
@ -843,7 +843,7 @@ impl<'a> Parser<'a> {
|
||||
|
||||
let sp = self.sess.source_map().start_point(self.token.span);
|
||||
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) {
|
||||
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp));
|
||||
err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
|
||||
}
|
||||
|
||||
Err(err)
|
||||
|
@ -403,9 +403,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
}
|
||||
|
||||
if let Some(suggestion) = suggestion {
|
||||
err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion });
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
ChangeImportBindingSuggestion { span: binding_span, suggestion },
|
||||
);
|
||||
} else {
|
||||
err.subdiagnostic(ChangeImportBinding { span: binding_span });
|
||||
err.subdiagnostic(self.dcx(), ChangeImportBinding { span: binding_span });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1430,17 +1433,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
);
|
||||
|
||||
if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
|
||||
err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span });
|
||||
err.subdiagnostic(self.dcx(), MaybeMissingMacroRulesName { span: ident.span });
|
||||
return;
|
||||
}
|
||||
|
||||
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
|
||||
err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
|
||||
err.subdiagnostic(self.dcx(), ExplicitUnsafeTraits { span: ident.span, ident });
|
||||
return;
|
||||
}
|
||||
|
||||
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
|
||||
err.subdiagnostic(AddedMacroUse);
|
||||
err.subdiagnostic(self.dcx(), AddedMacroUse);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1450,10 +1453,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
let span = self.def_span(def_id);
|
||||
let source_map = self.tcx.sess.source_map();
|
||||
let head_span = source_map.guess_head_span(span);
|
||||
err.subdiagnostic(ConsiderAddingADerive {
|
||||
err.subdiagnostic(
|
||||
self.dcx(),
|
||||
ConsiderAddingADerive {
|
||||
span: head_span.shrink_to_lo(),
|
||||
suggestion: "#[derive(Default)]\n".to_string(),
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
||||
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
||||
|
@ -1262,12 +1262,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
||||
// exclude decl_macro
|
||||
if self.get_macro_by_def_id(def_id).macro_rules =>
|
||||
{
|
||||
err.subdiagnostic(ConsiderAddingMacroExport {
|
||||
err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport {
|
||||
span: binding.span,
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
err.subdiagnostic(ConsiderMarkingAsPub {
|
||||
err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub {
|
||||
span: import.span,
|
||||
ident,
|
||||
});
|
||||
|
@ -1095,11 +1095,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||
Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
|
||||
Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
|
||||
};
|
||||
err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
|
||||
err.subdiagnostic(
|
||||
self.r.dcx(),
|
||||
errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
|
||||
span,
|
||||
ident: segment.ident,
|
||||
snippet,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
enum Side {
|
||||
@ -1191,10 +1194,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
|
||||
});
|
||||
|
||||
if let Some(param) = param {
|
||||
err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
|
||||
err.subdiagnostic(
|
||||
self.r.dcx(),
|
||||
errors::UnexpectedResChangeTyToConstParamSugg {
|
||||
span: param.shrink_to_lo(),
|
||||
applicability,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,21 +173,21 @@ pub fn add_feature_diagnostics_for_issue(
|
||||
feature_from_cli: bool,
|
||||
) {
|
||||
if let Some(n) = find_feature_issue(feature, issue) {
|
||||
err.subdiagnostic(FeatureDiagnosticForIssue { n });
|
||||
err.subdiagnostic(sess.dcx(), FeatureDiagnosticForIssue { n });
|
||||
}
|
||||
|
||||
// #23973: do not suggest `#![feature(...)]` if we are in beta/stable
|
||||
if sess.parse_sess.unstable_features.is_nightly_build() {
|
||||
if feature_from_cli {
|
||||
err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
|
||||
err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature });
|
||||
} else {
|
||||
err.subdiagnostic(FeatureDiagnosticHelp { feature });
|
||||
err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature });
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.ui_testing {
|
||||
err.subdiagnostic(SuggestUpgradeCompiler::ui_testing());
|
||||
err.subdiagnostic(sess.dcx(), SuggestUpgradeCompiler::ui_testing());
|
||||
} else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
|
||||
err.subdiagnostic(suggestion);
|
||||
err.subdiagnostic(sess.dcx(), suggestion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4830,11 +4830,14 @@ fn hint_missing_borrow<'tcx>(
|
||||
}
|
||||
|
||||
if !to_borrow.is_empty() {
|
||||
err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow });
|
||||
err.subdiagnostic(infcx.dcx(), errors::AdjustSignatureBorrow::Borrow { to_borrow });
|
||||
}
|
||||
|
||||
if !remove_borrow.is_empty() {
|
||||
err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow });
|
||||
err.subdiagnostic(
|
||||
infcx.dcx(),
|
||||
errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -504,7 +504,7 @@ pub fn report_msg<'tcx>(
|
||||
let is_local = machine.is_local(frame_info);
|
||||
// No span for non-local frames and the first frame (which is the error site).
|
||||
if is_local && idx > 0 {
|
||||
err.eager_subdiagnostic(err.dcx, frame_info.as_note(machine.tcx));
|
||||
err.subdiagnostic(err.dcx, frame_info.as_note(machine.tcx));
|
||||
} else {
|
||||
let sm = sess.source_map();
|
||||
let span = sm.span_to_embeddable_string(frame_info.span);
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
@ -40,6 +41,16 @@ impl Translate for SilentEmitter {
|
||||
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
|
||||
panic!("silent emitter attempted to translate a diagnostic");
|
||||
}
|
||||
|
||||
// Override `translate_message` for the silent emitter because eager translation of
|
||||
// subdiagnostics result in a call to this.
|
||||
fn translate_message<'a>(
|
||||
&'a self,
|
||||
message: &'a rustc_errors::DiagnosticMessage,
|
||||
_: &'a rustc_errors::translation::FluentArgs<'_>,
|
||||
) -> Result<Cow<'_, str>, rustc_errors::error::TranslateError<'_>> {
|
||||
rustc_errors::emitter::silent_translate(message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Emitter for SilentEmitter {
|
||||
|
@ -701,7 +701,7 @@ struct RawIdentDiagnosticArg {
|
||||
#[diag(no_crate_example)]
|
||||
struct SubdiagnosticBad {
|
||||
#[subdiagnostic(bad)]
|
||||
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
|
||||
note: Note,
|
||||
}
|
||||
|
||||
@ -717,7 +717,7 @@ struct SubdiagnosticBadStr {
|
||||
#[diag(no_crate_example)]
|
||||
struct SubdiagnosticBadTwice {
|
||||
#[subdiagnostic(bad, bad)]
|
||||
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
|
||||
note: Note,
|
||||
}
|
||||
|
||||
@ -725,7 +725,7 @@ struct SubdiagnosticBadTwice {
|
||||
#[diag(no_crate_example)]
|
||||
struct SubdiagnosticBadLitStr {
|
||||
#[subdiagnostic("bad")]
|
||||
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
|
||||
note: Note,
|
||||
}
|
||||
|
||||
@ -739,8 +739,9 @@ struct SubdiagnosticEagerLint {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(no_crate_example)]
|
||||
struct SubdiagnosticEagerCorrect {
|
||||
struct SubdiagnosticEagerFormerlyCorrect {
|
||||
#[subdiagnostic(eager)]
|
||||
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
|
||||
note: Note,
|
||||
}
|
||||
|
||||
@ -761,6 +762,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
|
||||
#[diag(no_crate_example)]
|
||||
struct SubdiagnosticEagerSuggestion {
|
||||
#[subdiagnostic(eager)]
|
||||
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
|
||||
sub: SubdiagnosticWithSuggestion,
|
||||
}
|
||||
|
||||
|
@ -468,11 +468,11 @@ LL | #[label]
|
||||
|
|
||||
= help: `#[label]` and `#[suggestion]` can only be applied to fields
|
||||
|
||||
error: `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
--> $DIR/diagnostic-derive.rs:703:7
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:703:5
|
||||
|
|
||||
LL | #[subdiagnostic(bad)]
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: `#[subdiagnostic = ...]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:711:5
|
||||
@ -480,40 +480,50 @@ error: `#[subdiagnostic = ...]` is not a valid attribute
|
||||
LL | #[subdiagnostic = "bad"]
|
||||
| ^
|
||||
|
||||
error: `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
--> $DIR/diagnostic-derive.rs:719:7
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:719:5
|
||||
|
|
||||
LL | #[subdiagnostic(bad, bad)]
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: `eager` is the only supported nested attribute for `subdiagnostic`
|
||||
--> $DIR/diagnostic-derive.rs:727:7
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:727:5
|
||||
|
|
||||
LL | #[subdiagnostic("bad")]
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^
|
||||
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:735:5
|
||||
|
|
||||
LL | #[subdiagnostic(eager)]
|
||||
| ^
|
||||
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:743:5
|
||||
|
|
||||
= help: eager subdiagnostics are not supported on lints
|
||||
LL | #[subdiagnostic(eager)]
|
||||
| ^
|
||||
|
||||
error: `#[subdiagnostic(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:764:5
|
||||
|
|
||||
LL | #[subdiagnostic(eager)]
|
||||
| ^
|
||||
|
||||
error: expected at least one string literal for `code(...)`
|
||||
--> $DIR/diagnostic-derive.rs:793:23
|
||||
--> $DIR/diagnostic-derive.rs:795:23
|
||||
|
|
||||
LL | #[suggestion(code())]
|
||||
| ^
|
||||
|
||||
error: `code(...)` must contain only string literals
|
||||
--> $DIR/diagnostic-derive.rs:801:23
|
||||
--> $DIR/diagnostic-derive.rs:803:23
|
||||
|
|
||||
LL | #[suggestion(code(foo))]
|
||||
| ^^^
|
||||
|
||||
error: `#[suggestion(...)]` is not a valid attribute
|
||||
--> $DIR/diagnostic-derive.rs:825:5
|
||||
--> $DIR/diagnostic-derive.rs:827:5
|
||||
|
|
||||
LL | #[suggestion(no_crate_suggestion, code = "")]
|
||||
| ^
|
||||
@ -529,13 +539,13 @@ LL | #[diag = "E0123"]
|
||||
| ^ maybe a missing crate `core`?
|
||||
|
||||
error[E0433]: failed to resolve: maybe a missing crate `core`?
|
||||
--> $DIR/diagnostic-derive.rs:801:23
|
||||
--> $DIR/diagnostic-derive.rs:803:23
|
||||
|
|
||||
LL | #[suggestion(code(foo))]
|
||||
| ^^^ maybe a missing crate `core`?
|
||||
|
||||
error[E0433]: failed to resolve: maybe a missing crate `core`?
|
||||
--> $DIR/diagnostic-derive.rs:810:25
|
||||
--> $DIR/diagnostic-derive.rs:812:25
|
||||
|
|
||||
LL | #[suggestion(code = 3)]
|
||||
| ^ maybe a missing crate `core`?
|
||||
@ -601,7 +611,7 @@ LL | #[diag(nonsense, code = E0123)]
|
||||
| ^^^^^^^^ not found in `crate::fluent_generated`
|
||||
|
||||
error[E0425]: cannot find value `__code_34` in this scope
|
||||
--> $DIR/diagnostic-derive.rs:807:10
|
||||
--> $DIR/diagnostic-derive.rs:809:10
|
||||
|
|
||||
LL | #[derive(Diagnostic)]
|
||||
| ^^^^^^^^^^ not found in this scope
|
||||
@ -622,7 +632,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::arg`
|
||||
--> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
|
||||
= note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: aborting due to 84 previous errors
|
||||
error: aborting due to 86 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0425, E0433.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
Loading…
Reference in New Issue
Block a user