1
Fork 0

Auto merge of #121240 - matthiaskrgr:rollup-lfb5i9w, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - #120952 (Don't use mem::zeroed in vec::IntoIter)
 - #121085 (errors: only eagerly translate subdiagnostics)
 - #121091 (use build.rustc config and skip-stage0-validation flag)
 - #121149 (Fix typo in VecDeque::handle_capacity_increase() doc comment.)
 - #121193 (Use fulfillment in next trait solver coherence)
 - #121209 (Make `CodegenBackend::join_codegen` infallible.)
 - #121210 (Fix `cfg(target_abi = "sim")` on `i386-apple-ios`)
 - #121228 (create stamp file for clippy)
 - #121231 (remove a couple of redundant clones)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-02-17 18:20:41 +00:00
commit cabdf3ad25
65 changed files with 718 additions and 496 deletions

View file

@ -229,7 +229,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
seen_spans.insert(move_span); 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 { if !is_loop_move {
err.span_label( err.span_label(
@ -291,18 +291,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if needs_note { if needs_note {
if let Some(local) = place.as_local() { if let Some(local) = place.as_local() {
let span = self.body.local_decls[local].source_info.span; let span = self.body.local_decls[local].source_info.span;
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { err.subdiagnostic(
is_partial_move, self.dcx(),
ty, crate::session_diagnostics::TypeNoCopy::Label {
place: &note_msg, is_partial_move,
span, ty,
}); place: &note_msg,
span,
},
);
} else { } else {
err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { err.subdiagnostic(
is_partial_move, self.dcx(),
ty, crate::session_diagnostics::TypeNoCopy::Note {
place: &note_msg, is_partial_move,
}); ty,
place: &note_msg,
},
);
}; };
} }
@ -557,7 +563,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
E0381, E0381,
"{used} binding {desc}{isnt_initialized}" "{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 if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action | InitializationRequiringAction::Assignment = desired_action
@ -848,9 +854,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&value_msg, &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::*; use crate::session_diagnostics::CaptureVarCause::*;
match kind { match kind {
hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span }, hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span },
@ -895,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_span, borrow_span,
&self.describe_any_place(borrow.borrowed_place.as_ref()), &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::*; use crate::session_diagnostics::CaptureVarCause::*;
let place = &borrow.borrowed_place; let place = &borrow.borrowed_place;
let desc_place = self.describe_any_place(place.as_ref()); let desc_place = self.describe_any_place(place.as_ref());
@ -1043,7 +1053,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"mutably borrow", "mutably borrow",
); );
borrow_spans.var_subdiag( borrow_spans.var_subdiag(
None, self.dcx(),
&mut err, &mut err,
Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }), Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }),
|kind, var_span| { |kind, var_span| {
@ -1131,22 +1141,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}; };
if issued_spans == borrow_spans { if issued_spans == borrow_spans {
borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { borrow_spans.var_subdiag(
use crate::session_diagnostics::CaptureVarCause::*; self.dcx(),
match kind { &mut err,
hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine { Some(gen_borrow_kind),
place: desc_place, |kind, var_span| {
var_span, use crate::session_diagnostics::CaptureVarCause::*;
is_single_var: false, match kind {
}, hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine {
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { place: desc_place,
BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } var_span,
is_single_var: false,
},
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
BorrowUsePlaceClosure {
place: desc_place,
var_span,
is_single_var: false,
}
}
} }
} },
}); );
} else { } else {
issued_spans.var_subdiag( issued_spans.var_subdiag(
Some(self.dcx()), self.dcx(),
&mut err, &mut err,
Some(issued_borrow.kind), Some(issued_borrow.kind),
|kind, var_span| { |kind, var_span| {
@ -1165,7 +1184,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
); );
borrow_spans.var_subdiag( borrow_spans.var_subdiag(
Some(self.dcx()), self.dcx(),
&mut err, &mut err,
Some(gen_borrow_kind), Some(gen_borrow_kind),
|kind, var_span| { |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(borrow_span, "borrowed value does not live long enough");
err.span_label(drop_span, format!("`{name}` dropped here while still borrowed")); 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 { crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_coroutine(), is_within: borrow_spans.for_coroutine(),
args_span, args_span,
@ -2476,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
None, None,
); );
borrow_spans.args_subdiag(&mut err, |args_span| { borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture { crate::session_diagnostics::CaptureArgLabel::Capture {
is_within: borrow_spans.for_coroutine(), is_within: borrow_spans.for_coroutine(),
args_span, args_span,
@ -2935,7 +2954,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
"assign", "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::*; use crate::session_diagnostics::CaptureVarCause::*;
match kind { match kind {
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, 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); 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::*; use crate::session_diagnostics::CaptureVarCause::*;
match kind { match kind {
hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, 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() { if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() {
let did = did.expect_local(); let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic( diag.subdiagnostic(
self.dcx(), self.dcx(),
OnClosureNote::InvokedTwice { OnClosureNote::InvokedTwice {
place_name: &ty::place_to_string_for_capture( 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() { if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() {
let did = did.expect_local(); let did = did.expect_local();
if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) {
diag.eager_subdiagnostic( diag.subdiagnostic(
self.dcx(), self.dcx(),
OnClosureNote::MovedTwice { OnClosureNote::MovedTwice {
place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), 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. /// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_subdiag( pub(super) fn args_subdiag(
self, self,
dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic, err: &mut Diagnostic,
f: impl FnOnce(Span) -> CaptureArgLabel, f: impl FnOnce(Span) -> CaptureArgLabel,
) { ) {
if let UseSpans::ClosureUse { args_span, .. } = self { 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` /// only adds label to the `path_span`
pub(super) fn var_path_only_subdiag( pub(super) fn var_path_only_subdiag(
self, self,
dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic, err: &mut Diagnostic,
action: crate::InitializationRequiringAction, action: crate::InitializationRequiringAction,
) { ) {
@ -607,20 +609,26 @@ impl UseSpans<'_> {
if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self { if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self {
match closure_kind { match closure_kind {
hir::ClosureKind::Coroutine(_) => { hir::ClosureKind::Coroutine(_) => {
err.subdiagnostic(match action { err.subdiagnostic(
Borrow => BorrowInCoroutine { path_span }, dcx,
MatchOn | Use => UseInCoroutine { path_span }, match action {
Assignment => AssignInCoroutine { path_span }, Borrow => BorrowInCoroutine { path_span },
PartialAssignment => AssignPartInCoroutine { path_span }, MatchOn | Use => UseInCoroutine { path_span },
}); Assignment => AssignInCoroutine { path_span },
PartialAssignment => AssignPartInCoroutine { path_span },
},
);
} }
hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => {
err.subdiagnostic(match action { err.subdiagnostic(
Borrow => BorrowInClosure { path_span }, dcx,
MatchOn | Use => UseInClosure { path_span }, match action {
Assignment => AssignInClosure { path_span }, Borrow => BorrowInClosure { path_span },
PartialAssignment => AssignPartInClosure { 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. /// Add a subdiagnostic to the use of the captured variable, if it exists.
pub(super) fn var_subdiag( pub(super) fn var_subdiag(
self, self,
dcx: Option<&rustc_errors::DiagCtxt>, dcx: &rustc_errors::DiagCtxt,
err: &mut Diagnostic, err: &mut Diagnostic,
kind: Option<rustc_middle::mir::BorrowKind>, kind: Option<rustc_middle::mir::BorrowKind>,
f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause, f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause,
) { ) {
if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self { if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self {
if capture_kind_span != path_span { if capture_kind_span != path_span {
err.subdiagnostic(match kind { err.subdiagnostic(
Some(kd) => match kd { dcx,
rustc_middle::mir::BorrowKind::Shared match kind {
| rustc_middle::mir::BorrowKind::Fake => { Some(kd) => match kd {
CaptureVarKind::Immut { kind_span: capture_kind_span } rustc_middle::mir::BorrowKind::Shared
} | rustc_middle::mir::BorrowKind::Fake => {
CaptureVarKind::Immut { kind_span: capture_kind_span }
}
rustc_middle::mir::BorrowKind::Mut { .. } => { rustc_middle::mir::BorrowKind::Mut { .. } => {
CaptureVarKind::Mut { kind_span: capture_kind_span } 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); let diag = f(closure_kind, path_span);
match dcx { err.subdiagnostic(dcx, diag);
Some(hd) => err.eager_subdiagnostic(hd, diag),
None => err.subdiagnostic(diag),
};
} }
} }
@ -1025,26 +1033,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
CallKind::FnCall { fn_trait_id, .. } CallKind::FnCall { fn_trait_id, .. }
if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() => if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() =>
{ {
err.subdiagnostic(CaptureReasonLabel::Call { err.subdiagnostic(
fn_call_span, self.dcx(),
place_name: &place_name, CaptureReasonLabel::Call {
is_partial, fn_call_span,
is_loop_message, place_name: &place_name,
}); is_partial,
err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); is_loop_message,
},
);
err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span });
} }
CallKind::Operator { self_arg, .. } => { CallKind::Operator { self_arg, .. } => {
let self_arg = self_arg.unwrap(); let self_arg = self_arg.unwrap();
err.subdiagnostic(CaptureReasonLabel::OperatorUse { err.subdiagnostic(
fn_call_span, self.dcx(),
place_name: &place_name, CaptureReasonLabel::OperatorUse {
is_partial, fn_call_span,
is_loop_message, place_name: &place_name,
}); is_partial,
is_loop_message,
},
);
if self.fn_self_span_reported.insert(fn_span) { if self.fn_self_span_reported.insert(fn_span) {
err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator { err.subdiagnostic(
span: self_arg.span, self.dcx(),
}); CaptureReasonNote::LhsMoveByOperator { span: self_arg.span },
);
} }
} }
CallKind::Normal { self_arg, desugaring, method_did, method_args } => { 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); let func = tcx.def_path_str(method_did);
err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { err.subdiagnostic(
func, self.dcx(),
place_name: place_name.clone(), CaptureReasonNote::FuncTakeSelf {
span: self_arg.span, func,
}); place_name: place_name.clone(),
span: self_arg.span,
},
);
} }
let parent_did = tcx.parent(method_did); let parent_did = tcx.parent(method_did);
let parent_self_ty = 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)) matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result))
}); });
if is_option_or_result && maybe_reinitialized_locations_is_empty { 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 { if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring {
let ty = moved_place.ty(self.body, tcx).ty; let ty = moved_place.ty(self.body, tcx).ty;
@ -1093,18 +1114,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
_ => false, _ => false,
}; };
if suggest { if suggest {
err.subdiagnostic(CaptureReasonSuggest::IterateSlice { err.subdiagnostic(
ty, self.dcx(),
span: move_span.shrink_to_lo(), CaptureReasonSuggest::IterateSlice {
}); ty,
span: move_span.shrink_to_lo(),
},
);
} }
err.subdiagnostic(CaptureReasonLabel::ImplicitCall { err.subdiagnostic(
fn_call_span, self.dcx(),
place_name: &place_name, CaptureReasonLabel::ImplicitCall {
is_partial, fn_call_span,
is_loop_message, place_name: &place_name,
}); is_partial,
is_loop_message,
},
);
// If the moved place was a `&mut` ref, then we can // If the moved place was a `&mut` ref, then we can
// suggest to reborrow it where it was moved, so it // suggest to reborrow it where it was moved, so it
// will still be valid by the time we get to the usage. // will still be valid by the time we get to the usage.
@ -1128,19 +1155,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} else { } else {
if let Some((CallDesugaringKind::Await, _)) = desugaring { if let Some((CallDesugaringKind::Await, _)) = desugaring {
err.subdiagnostic(CaptureReasonLabel::Await { err.subdiagnostic(
fn_call_span, self.dcx(),
place_name: &place_name, CaptureReasonLabel::Await {
is_partial, fn_call_span,
is_loop_message, place_name: &place_name,
}); is_partial,
is_loop_message,
},
);
} else { } else {
err.subdiagnostic(CaptureReasonLabel::MethodCall { err.subdiagnostic(
fn_call_span, self.dcx(),
place_name: &place_name, CaptureReasonLabel::MethodCall {
is_partial, fn_call_span,
is_loop_message, place_name: &place_name,
}); is_partial,
is_loop_message,
},
);
} }
// Erase and shadow everything that could be passed to the new infcx. // Erase and shadow everything that could be passed to the new infcx.
let ty = moved_place.ty(self.body, tcx).ty; 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) && self.infcx.can_eq(self.param_env, ty, self_ty)
{ {
err.eager_subdiagnostic( err.subdiagnostic(
self.dcx(), self.dcx(),
CaptureReasonSuggest::FreshReborrow { CaptureReasonSuggest::FreshReborrow {
span: move_span.shrink_to_hi(), span: move_span.shrink_to_hi(),
@ -1239,17 +1272,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} }
} else { } else {
if move_span != span || is_loop_message { if move_span != span || is_loop_message {
err.subdiagnostic(CaptureReasonLabel::MovedHere { err.subdiagnostic(
move_span, self.dcx(),
is_partial, CaptureReasonLabel::MovedHere {
is_move_msg, move_span,
is_loop_message, is_partial,
}); is_move_msg,
is_loop_message,
},
);
} }
// If the move error occurs due to a loop, don't show // If the move error occurs due to a loop, don't show
// another message for the same span // another message for the same span
if !is_loop_message { 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(_) => { hir::ClosureKind::Coroutine(_) => {
CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial } CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial }
} }

View file

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

View file

@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
} }
if suggest { if suggest {
borrow_spans.var_subdiag( borrow_spans.var_subdiag(
None, self.dcx(),
&mut err, &mut err,
Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }),
|_kind, var_span| { |_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 upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap();
let upvar_def_span = self.infcx.tcx.hir().span(def_hir); let upvar_def_span = self.infcx.tcx.hir().span(def_hir);
let upvar_span = upvars_map.get(&def_hir).unwrap().span; let upvar_span = upvars_map.get(&def_hir).unwrap().span;
diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span }); diag.subdiagnostic(self.dcx(), VarHereDenote::Defined { span: upvar_def_span });
diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span }); diag.subdiagnostic(self.dcx(), VarHereDenote::Captured { span: upvar_span });
} }
} }
if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().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); 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.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr);
self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr); self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr);
@ -979,7 +979,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
ident.span, ident.span,
"calling this method introduces the `impl`'s `'static` requirement", "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( err.span_suggestion_verbose(
span.shrink_to_hi(), span.shrink_to_hi(),
"consider relaxing the implicit `'static` requirement", "consider relaxing the implicit `'static` requirement",

View file

@ -233,11 +233,11 @@ impl CodegenBackend for CraneliftCodegenBackend {
ongoing_codegen: Box<dyn Any>, ongoing_codegen: Box<dyn Any>,
sess: &Session, sess: &Session,
_outputs: &OutputFilenames, _outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
Ok(ongoing_codegen ongoing_codegen
.downcast::<driver::aot::OngoingCodegen>() .downcast::<driver::aot::OngoingCodegen>()
.unwrap() .unwrap()
.join(sess, self.config.borrow().as_ref().unwrap())) .join(sess, self.config.borrow().as_ref().unwrap())
} }
fn link( fn link(

View file

@ -122,7 +122,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
diag.span(span); diag.span(span);
}; };
if let Some(missing_features) = self.missing_features { if let Some(missing_features) = self.missing_features {
diag.subdiagnostic(missing_features); diag.subdiagnostic(dcx, missing_features);
} }
diag.arg("features", self.features.join(", ")); diag.arg("features", self.features.join(", "));
diag diag

View file

@ -217,13 +217,11 @@ impl CodegenBackend for GccCodegenBackend {
Box::new(res) Box::new(res)
} }
fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
let (codegen_results, work_products) = ongoing_codegen ongoing_codegen
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>() .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
.expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>") .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
.join(sess); .join(sess)
Ok((codegen_results, work_products))
} }
fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {

View file

@ -131,7 +131,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl
diag.span(span); diag.span(span);
}; };
if let Some(missing_features) = self.missing_features { if let Some(missing_features) = self.missing_features {
diag.subdiagnostic(missing_features); diag.subdiagnostic(dcx, missing_features);
} }
diag.arg("features", self.features.join(", ")); diag.arg("features", self.features.join(", "));
diag diag

View file

@ -369,7 +369,7 @@ impl CodegenBackend for LlvmCodegenBackend {
ongoing_codegen: Box<dyn Any>, ongoing_codegen: Box<dyn Any>,
sess: &Session, sess: &Session,
outputs: &OutputFilenames, outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
let (codegen_results, work_products) = ongoing_codegen let (codegen_results, work_products) = ongoing_codegen
.downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>() .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
.expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>") .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend {
}); });
} }
Ok((codegen_results, work_products)) (codegen_results, work_products)
} }
fn link( fn link(

View file

@ -102,7 +102,7 @@ pub trait CodegenBackend {
ongoing_codegen: Box<dyn Any>, ongoing_codegen: Box<dyn Any>,
sess: &Session, sess: &Session,
outputs: &OutputFilenames, outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed>; ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>);
/// This is called on the returned `CodegenResults` from `join_codegen` /// This is called on the returned `CodegenResults` from `join_codegen`
fn link( fn link(

View file

@ -131,7 +131,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
// FIXME(effects) revisit this // FIXME(effects) revisit this
if !tcx.is_const_trait_impl_raw(data.impl_def_id) { if !tcx.is_const_trait_impl_raw(data.impl_def_id) {
let span = tcx.def_span(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 });
} }
} }
} }

View file

@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage {
/// Translatable message which has already been translated eagerly. /// Translatable message which has already been translated eagerly.
/// ///
/// Some diagnostics have repeated subdiagnostics where the same interpolated variables would /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
/// be instantiated multiple times with different values. As translation normally happens /// be instantiated multiple times with different values. These subdiagnostics' messages
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, /// are translated when they are added to the parent diagnostic, producing this variant of
/// the setting of diagnostic arguments in the derived code will overwrite previous variable /// `DiagnosticMessage`.
/// values and only the final value will be set when translation occurs - resulting in Translated(Cow<'static, str>),
/// 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>),
/// Identifier of a Fluent message. Instances of this variant are generated by the /// Identifier of a Fluent message. Instances of this variant are generated by the
/// `Subdiagnostic` derive. /// `Subdiagnostic` derive.
FluentIdentifier(FluentId), FluentIdentifier(FluentId),
@ -307,19 +303,15 @@ impl From<Cow<'static, str>> for SubdiagnosticMessage {
pub enum DiagnosticMessage { pub enum DiagnosticMessage {
/// Non-translatable diagnostic message. /// Non-translatable diagnostic message.
Str(Cow<'static, str>), 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 /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would
/// be instantiated multiple times with different values. As translation normally happens /// be instantiated multiple times with different values. These subdiagnostics' messages
/// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, /// are translated when they are added to the parent diagnostic, producing this variant of
/// the setting of diagnostic arguments in the derived code will overwrite previous variable /// `DiagnosticMessage`.
/// values and only the final value will be set when translation occurs - resulting in Translated(Cow<'static, str>),
/// 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>),
/// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic /// 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/hello.html>
/// <https://projectfluent.org/fluent/guide/attributes.html> /// <https://projectfluent.org/fluent/guide/attributes.html>
@ -336,7 +328,7 @@ impl DiagnosticMessage {
pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self {
let attr = match sub { let attr = match sub {
SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s),
SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s), SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s),
SubdiagnosticMessage::FluentIdentifier(id) => { SubdiagnosticMessage::FluentIdentifier(id) => {
return DiagnosticMessage::FluentIdentifier(id, None); return DiagnosticMessage::FluentIdentifier(id, None);
} }
@ -345,7 +337,7 @@ impl DiagnosticMessage {
match self { match self {
DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), 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, _) => {
DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr))
} }
@ -354,7 +346,7 @@ impl DiagnosticMessage {
pub fn as_str(&self) -> Option<&str> { pub fn as_str(&self) -> Option<&str> {
match self { match self {
DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s), DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s),
DiagnosticMessage::FluentIdentifier(_, _) => None, DiagnosticMessage::FluentIdentifier(_, _) => None,
} }
} }
@ -396,7 +388,7 @@ impl Into<SubdiagnosticMessage> for DiagnosticMessage {
fn into(self) -> SubdiagnosticMessage { fn into(self) -> SubdiagnosticMessage {
match self { match self {
DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s),
DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s), DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s),
DiagnosticMessage::FluentIdentifier(id, None) => { DiagnosticMessage::FluentIdentifier(id, None) => {
SubdiagnosticMessage::FluentIdentifier(id) SubdiagnosticMessage::FluentIdentifier(id)
} }

View file

@ -851,18 +851,11 @@ impl Diagnostic {
self 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 /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see
/// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// [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 /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of
/// interpolated variables). /// interpolated variables).
pub fn eager_subdiagnostic( pub fn subdiagnostic(
&mut self, &mut self,
dcx: &crate::DiagCtxt, dcx: &crate::DiagCtxt,
subdiagnostic: impl AddToDiagnostic, subdiagnostic: impl AddToDiagnostic,
@ -918,7 +911,7 @@ impl Diagnostic {
/// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// 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 /// combining it with the primary message of the diagnostic (if translatable, otherwise it just
/// passes the user's string along). /// passes the user's string along).
fn subdiagnostic_message_to_diagnostic_message( pub(crate) fn subdiagnostic_message_to_diagnostic_message(
&self, &self,
attr: impl Into<SubdiagnosticMessage>, attr: impl Into<SubdiagnosticMessage>,
) -> DiagnosticMessage { ) -> DiagnosticMessage {

View file

@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg, name: impl Into<Cow<'static, str>>, arg: impl IntoDiagnosticArg,
)); ));
forward!((subdiagnostic, with_subdiagnostic)( forward!((subdiagnostic, with_subdiagnostic)(
subdiagnostic: impl crate::AddToDiagnostic,
));
forward!((eager_subdiagnostic, with_eager_subdiagnostic)(
dcx: &DiagCtxt, dcx: &DiagCtxt,
subdiagnostic: impl crate::AddToDiagnostic, subdiagnostic: impl crate::AddToDiagnostic,
)); ));

View file

@ -10,6 +10,7 @@
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::{FileLines, FileName, SourceFile, Span}; use rustc_span::{FileLines, FileName, SourceFile, Span};
use crate::error::TranslateError;
use crate::snippet::{ use crate::snippet::{
Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString,
}; };
@ -559,6 +560,18 @@ pub struct SilentEmitter {
pub fatal_note: String, 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 { impl Translate for SilentEmitter {
fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> { fn fluent_bundle(&self) -> Option<&Lrc<FluentBundle>> {
None None
@ -567,6 +580,16 @@ impl Translate for SilentEmitter {
fn fallback_fluent_bundle(&self) -> &FluentBundle { fn fallback_fluent_bundle(&self) -> &FluentBundle {
panic!("silent emitter attempted to translate message") 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 { impl Emitter for SilentEmitter {

View file

@ -643,7 +643,8 @@ impl DiagCtxt {
message: DiagnosticMessage, message: DiagnosticMessage,
args: impl Iterator<Item = DiagnosticArg<'a>>, args: impl Iterator<Item = DiagnosticArg<'a>>,
) -> SubdiagnosticMessage { ) -> 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`. /// Translate `message` eagerly with `args` to `String`.
@ -653,8 +654,7 @@ impl DiagCtxt {
args: impl Iterator<Item = DiagnosticArg<'a>>, args: impl Iterator<Item = DiagnosticArg<'a>>,
) -> String { ) -> String {
let inner = self.inner.borrow(); let inner = self.inner.borrow();
let args = crate::translation::to_fluent_args(args); inner.eagerly_translate_to_string(message, args)
inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string()
} }
// This is here to not allow mutation of flags; // This is here to not allow mutation of flags;
@ -1464,6 +1464,25 @@ impl DiagCtxtInner {
.or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) .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) { fn flush_delayed(&mut self) {
if self.delayed_bugs.is_empty() { if self.delayed_bugs.is_empty() {
return; return;
@ -1502,15 +1521,22 @@ impl DiagCtxtInner {
} }
let mut bug = 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). // "Undelay" the delayed bugs (into plain `Bug`s).
if bug.level != DelayedBug { if bug.level != DelayedBug {
// NOTE(eddyb) not panicking here because we're already producing // NOTE(eddyb) not panicking here because we're already producing
// an ICE, and the more information the merrier. // an ICE, and the more information the merrier.
bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { let subdiag = InvalidFlushedDelayedDiagnosticLevel {
span: bug.span.primary_span().unwrap(), span: bug.span.primary_span().unwrap(),
level: bug.level, 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; bug.level = Bug;
@ -1545,25 +1571,35 @@ impl DelayedDiagnostic {
DelayedDiagnostic { inner: diagnostic, note: backtrace } 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() { match self.note.status() {
BacktraceStatus::Captured => { BacktraceStatus::Captured => {
let inner = &self.inner; let inner = &self.inner;
self.inner.subdiagnostic(DelayedAtWithNewline { let subdiag = DelayedAtWithNewline {
span: inner.span.primary_span().unwrap_or(DUMMY_SP), span: inner.span.primary_span().unwrap_or(DUMMY_SP),
emitted_at: inner.emitted_at.clone(), emitted_at: inner.emitted_at.clone(),
note: self.note, note: self.note,
}); };
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
} }
// Avoid the needless newline when no backtrace has been captured, // Avoid the needless newline when no backtrace has been captured,
// the display impl should just be a single line. // the display impl should just be a single line.
_ => { _ => {
let inner = &self.inner; let inner = &self.inner;
self.inner.subdiagnostic(DelayedAtWithoutNewline { let subdiag = DelayedAtWithoutNewline {
span: inner.span.primary_span().unwrap_or(DUMMY_SP), span: inner.span.primary_span().unwrap_or(DUMMY_SP),
emitted_at: inner.emitted_at.clone(), emitted_at: inner.emitted_at.clone(),
note: self.note, note: self.note,
}); };
subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with);
} }
} }
@ -1709,15 +1745,15 @@ impl Level {
} }
// FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. // 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, source_map: &SourceMap,
diag: &mut Diagnostic, diag: &mut DiagnosticBuilder<'_, E>,
n: usize, n: usize,
path_span: Span, path_span: Span,
incl_angl_brckt: bool, incl_angl_brckt: bool,
insertion_span: Span, 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) { if !source_map.is_span_accessible(insertion_span) {
// Do not try to suggest anything if generated by a proc-macro. // Do not try to suggest anything if generated by a proc-macro.
return; return;
@ -1726,11 +1762,10 @@ pub fn add_elided_lifetime_in_path_suggestion(
let suggestion = let suggestion =
if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") }; if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") };
diag.subdiagnostic(IndicateAnonymousLifetime { diag.subdiagnostic(
span: insertion_span.shrink_to_hi(), diag.dcx,
count: n, IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion },
suggestion, );
});
} }
pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( pub fn report_ambiguity_error<'a, G: EmissionGuarantee>(

View file

@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind};
use crate::snippet::Style; use crate::snippet::Style;
use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle};
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_error_messages::FluentArgs; pub use rustc_error_messages::FluentArgs;
use std::borrow::Cow; use std::borrow::Cow;
use std::env; use std::env;
use std::error::Report; use std::error::Report;
@ -61,7 +61,7 @@ pub trait Translate {
) -> Result<Cow<'_, str>, TranslateError<'_>> { ) -> Result<Cow<'_, str>, TranslateError<'_>> {
trace!(?message, ?args); trace!(?message, ?args);
let (identifier, attr) = match message { let (identifier, attr) = match message {
DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => { DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => {
return Ok(Cow::Borrowed(msg)); return Ok(Cow::Borrowed(msg));
} }
DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr),

View file

@ -7,7 +7,7 @@ use crate::mbe::{
use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::token::{self, Token, TokenKind};
use rustc_ast::tokenstream::TokenStream; use rustc_ast::tokenstream::TokenStream;
use rustc_ast_pretty::pprust; 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_parse::parser::{Parser, Recovery};
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::symbol::Ident; 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"); 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() { if let Some(span) = remaining_matcher.span() {
err.span_note(span, format!("while trying to match {remaining_matcher}")); 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 let Ok(src) = sm.span_to_snippet(span) {
if src.starts_with("///") || src.starts_with("/**") { 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("/*!") { } else if src.starts_with("//!") || src.starts_with("/*!") {
err.subdiagnostic(ExplainDocComment::Inner { span }); err.subdiagnostic(dcx, ExplainDocComment::Inner { span });
} }
} }
} }

View file

@ -454,7 +454,7 @@ pub fn compile_declarative_macro(
let sp = token.span.substitute_dummy(def.span); let sp = token.span.substitute_dummy(def.span);
let mut err = sess.dcx().struct_span_err(sp, s); let mut err = sess.dcx().struct_span_err(sp, s);
err.span_label(sp, msg); 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(); err.emit();
return dummy_syn_ext(); return dummy_syn_ext();
} }

View file

@ -260,7 +260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi()); let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi());
let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi }; 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, /// When the previously checked expression (the scrutinee) diverges,
@ -311,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
error: &mut bool, error: &mut bool,
) { ) {
if let Some((if_span, msg)) = ret_reason { if let Some((if_span, msg)) = ret_reason {
err.span_label(if_span, msg.clone()); err.span_label(if_span, msg);
} else if let ExprKind::Block(block, _) = then_expr.kind } else if let ExprKind::Block(block, _) = then_expr.kind
&& let Some(expr) = block.expr && let Some(expr) = block.expr
{ {

View file

@ -993,19 +993,25 @@ impl<'a, 'tcx> CastCheck<'tcx> {
if let Some((deref_ty, _)) = derefed { if let Some((deref_ty, _)) = derefed {
// Give a note about what the expr derefs to. // Give a note about what the expr derefs to.
if deref_ty != self.expr_ty.peel_refs() { if deref_ty != self.expr_ty.peel_refs() {
err.subdiagnostic(errors::DerefImplsIsEmpty { err.subdiagnostic(
span: self.expr_span, fcx.dcx(),
deref_ty: fcx.ty_to_string(deref_ty), errors::DerefImplsIsEmpty {
}); span: self.expr_span,
deref_ty: fcx.ty_to_string(deref_ty),
},
);
} }
// Create a multipart suggestion: add `!` and `.is_empty()` in // Create a multipart suggestion: add `!` and `.is_empty()` in
// place of the cast. // place of the cast.
err.subdiagnostic(errors::UseIsEmpty { err.subdiagnostic(
lo: self.expr_span.shrink_to_lo(), fcx.dcx(),
hi: self.span.with_lo(self.expr_span.hi()), errors::UseIsEmpty {
expr_ty: fcx.ty_to_string(self.expr_ty), 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),
},
);
} }
} }
} }

View file

@ -396,7 +396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if let Some(sp) = if let Some(sp) =
tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&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()); oprnd_t = Ty::new_error(tcx, err.emit());
} }
@ -2048,7 +2048,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.shrink_to_hi() .shrink_to_hi()
.to(range_end.span); .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 },
);
} }
} }

View file

@ -1269,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{ {
// The user provided `ptr::null()`, but the function expects // The user provided `ptr::null()`, but the function expects
// `ptr::null_mut()`. // `ptr::null_mut()`.
err.subdiagnostic(SuggestPtrNullMut { span: arg.span }); err.subdiagnostic(self.dcx(), SuggestPtrNullMut { span: arg.span });
} }
} }

View file

@ -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. // 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 { if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref {
let sugg = prefix_wrap(".as_ref()"); let sugg = prefix_wrap(".as_ref()");
err.subdiagnostic(errors::SuggestConvertViaMethod { err.subdiagnostic(
span: expr.span.shrink_to_hi(), self.dcx(),
sugg, errors::SuggestConvertViaMethod {
expected, span: expr.span.shrink_to_hi(),
found, sugg,
borrow_removal_span, expected,
}); found,
borrow_removal_span,
},
);
return true; return true;
} else if let Some((deref_ty, _)) = } else if let Some((deref_ty, _)) =
self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1) 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 && error_tys_equate_as_ref
{ {
let sugg = prefix_wrap(".as_deref()"); let sugg = prefix_wrap(".as_deref()");
err.subdiagnostic(errors::SuggestConvertViaMethod { err.subdiagnostic(
span: expr.span.shrink_to_hi(), self.dcx(),
sugg, errors::SuggestConvertViaMethod {
expected, span: expr.span.shrink_to_hi(),
found, sugg,
borrow_removal_span, expected,
}); found,
borrow_removal_span,
},
);
return true; return true;
} else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind() } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind()
&& Some(adt.did()) == self.tcx.lang_items().string() && Some(adt.did()) == self.tcx.lang_items().string()
@ -565,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
end: span.shrink_to_hi(), end: span.shrink_to_hi(),
}, },
}; };
err.subdiagnostic(suggest_boxing); err.subdiagnostic(self.dcx(), suggest_boxing);
true true
} else { } else {
@ -799,29 +805,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match &fn_decl.output { match &fn_decl.output {
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => { &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => {
// `fn main()` must return `()`, do not suggest changing return type // `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; return true;
} }
&hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => {
if let Some(found) = found.make_suggestable(self.tcx, false) { if let Some(found) = found.make_suggestable(self.tcx, false) {
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { err.subdiagnostic(
span, self.dcx(),
found: found.to_string(), errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() },
}); );
return true; return true;
} else if let ty::Closure(_, args) = found.kind() } else if let ty::Closure(_, args) = found.kind()
// FIXME(compiler-errors): Get better at printing binders... // FIXME(compiler-errors): Get better at printing binders...
&& let closure = args.as_closure() && let closure = args.as_closure()
&& closure.sig().is_suggestable(self.tcx, false) && closure.sig().is_suggestable(self.tcx, false)
{ {
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { err.subdiagnostic(
span, self.dcx(),
found: closure.print_as_impl_trait().to_string(), errors::AddReturnTypeSuggestion::Add {
}); span,
found: closure.print_as_impl_trait().to_string(),
},
);
return true; return true;
} else { } else {
// FIXME: if `found` could be `impl Iterator` we should suggest that. // 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; return true;
} }
} }
@ -843,16 +855,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!(?found); debug!(?found);
if found.is_suggestable(self.tcx, false) { if found.is_suggestable(self.tcx, false) {
if term.span.is_empty() { if term.span.is_empty() {
err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { err.subdiagnostic(
span: term.span, self.dcx(),
found: found.to_string(), errors::AddReturnTypeSuggestion::Add {
}); span: term.span,
found: found.to_string(),
},
);
return true; return true;
} else { } else {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { err.subdiagnostic(
span: term.span, self.dcx(),
expected, errors::ExpectedReturnTypeLabel::Other {
}); span: term.span,
expected,
},
);
} }
} }
} else { } else {
@ -867,10 +885,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty = self.normalize(hir_ty.span, ty); let ty = self.normalize(hir_ty.span, ty);
let ty = self.tcx.instantiate_bound_regions_with_erased(ty); let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
if self.can_coerce(expected, ty) { if self.can_coerce(expected, ty) {
err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { err.subdiagnostic(
span: hir_ty.span, self.dcx(),
expected, errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected },
}); );
self.try_suggest_return_impl_trait(err, expected, ty, fn_id); self.try_suggest_return_impl_trait(err, expected, ty, fn_id);
return true; 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); 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) { 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 }` // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }`
err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp));
true true
} else { } else {
false false
@ -1220,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else { } else {
return false; return false;
}; };
diag.subdiagnostic(subdiag); diag.subdiagnostic(self.dcx(), subdiag);
return true; return true;
} }
} }

View file

@ -3269,19 +3269,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if impls_trait(trait_info.def_id) { if impls_trait(trait_info.def_id) {
self.suggest_valid_traits(err, vec![trait_info.def_id], false); self.suggest_valid_traits(err, vec![trait_info.def_id], false);
} else { } else {
err.subdiagnostic(CandidateTraitNote { err.subdiagnostic(
span: self.tcx.def_span(trait_info.def_id), self.dcx(),
trait_name: self.tcx.def_path_str(trait_info.def_id), CandidateTraitNote {
item_name, span: self.tcx.def_span(trait_info.def_id),
action_or_ty: if trait_missing_method { trait_name: self.tcx.def_path_str(trait_info.def_id),
"NONE".to_string() item_name,
} else { action_or_ty: if trait_missing_method {
param_type.map_or_else( "NONE".to_string()
|| "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. } else {
ToString::to_string, param_type.map_or_else(
) || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
ToString::to_string,
)
},
}, },
}); );
} }
} }
trait_infos => { trait_infos => {

View file

@ -824,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If the previous expression was a block expression, suggest parentheses // If the previous expression was a block expression, suggest parentheses
// (turning this into a binary subtraction operation instead.) // (turning this into a binary subtraction operation instead.)
// for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs) // 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 { } else {
match actual.kind() { match actual.kind() {
Uint(_) if op == hir::UnOp::Neg => { Uint(_) if op == hir::UnOp::Neg => {

View file

@ -845,7 +845,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
arm_ty, arm_ty,
arm_span, arm_span,
) { ) {
err.subdiagnostic(subdiag); err.subdiagnostic(self.dcx(), subdiag);
} }
if let Some(ret_sp) = opt_suggest_box_span { if let Some(ret_sp) = opt_suggest_box_span {
// Get return type span and point to it. // Get return type span and point to it.
@ -882,7 +882,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
else_ty, else_ty,
else_span, else_span,
) { ) {
err.subdiagnostic(subdiag); err.subdiagnostic(self.dcx(), subdiag);
} }
// don't suggest wrapping either blocks in `if .. {} else {}` // don't suggest wrapping either blocks in `if .. {} else {}`
let is_empty_arm = |id| { let is_empty_arm = |id| {

View file

@ -342,7 +342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
trait_predicates: trait_predicates.join(", "), trait_predicates: trait_predicates.join(", "),
} }
}; };
err.subdiagnostic(suggestion); err.subdiagnostic(self.dcx(), suggestion);
} }
pub(super) fn report_placeholder_failure( pub(super) fn report_placeholder_failure(

View file

@ -84,7 +84,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)), start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)),
end_sp: return_sp.shrink_to_hi(), end_sp: return_sp.shrink_to_hi(),
}; };
err.subdiagnostic(sugg); err.subdiagnostic(self.dcx(), sugg);
let mut starts = Vec::new(); let mut starts = Vec::new();
let mut ends = Vec::new(); let mut ends = Vec::new();
@ -93,7 +93,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
ends.push(span.shrink_to_hi()); ends.push(span.shrink_to_hi());
} }
let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends }; let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends };
err.subdiagnostic(sugg); err.subdiagnostic(self.dcx(), sugg);
} }
pub(super) fn suggest_tuple_pattern( pub(super) fn suggest_tuple_pattern(
@ -138,7 +138,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
span_low: cause.span.shrink_to_lo(), span_low: cause.span.shrink_to_lo(),
span_high: cause.span.shrink_to_hi(), span_high: cause.span.shrink_to_hi(),
}; };
diag.subdiagnostic(sugg); diag.subdiagnostic(self.dcx(), sugg);
} }
_ => { _ => {
// More than one matching variant. // More than one matching variant.
@ -147,7 +147,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
cause_span: cause.span, cause_span: cause.span,
compatible_variants, 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) => { (_, 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 // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic
diag.subdiagnostic(ConsiderAddingAwait::FutureSugg { diag.subdiagnostic(
span: exp_span.shrink_to_hi(), self.dcx(),
}); ConsiderAddingAwait::FutureSugg { span: exp_span.shrink_to_hi() },
);
Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span }) Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span })
} }
(Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
@ -249,7 +250,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
_ => None, _ => None,
}; };
if let Some(subdiag) = subdiag { if let Some(subdiag) = subdiag {
diag.subdiagnostic(subdiag); diag.subdiagnostic(self.dcx(), subdiag);
} }
} }
@ -285,7 +286,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} else { } else {
return; return;
}; };
diag.subdiagnostic(suggestion); diag.subdiagnostic(self.dcx(), suggestion);
} }
} }
} }
@ -325,15 +326,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
(true, false) => FunctionPointerSuggestion::UseRef { span, fn_name }, (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name },
(false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name }, (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name },
(true, true) => { (true, true) => {
diag.subdiagnostic(FnItemsAreDistinct); diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig } FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig }
} }
(false, false) => { (false, false) => {
diag.subdiagnostic(FnItemsAreDistinct); diag.subdiagnostic(self.dcx(), FnItemsAreDistinct);
FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig } FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig }
} }
}; };
diag.subdiagnostic(sugg); diag.subdiagnostic(self.dcx(), sugg);
} }
(ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => { (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => {
let expected_sig = let expected_sig =
@ -342,7 +343,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
&(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2)); &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2));
if self.same_type_modulo_infer(*expected_sig, *found_sig) { 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) if !self.same_type_modulo_infer(*found_sig, *expected_sig)
@ -371,7 +372,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
} }
}; };
diag.subdiagnostic(sug); diag.subdiagnostic(self.dcx(), sug);
} }
(ty::FnDef(did, args), ty::FnPtr(sig)) => { (ty::FnDef(did, args), ty::FnPtr(sig)) => {
let expected_sig = let expected_sig =
@ -390,7 +391,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
format!("{fn_name} as {found_sig}") format!("{fn_name} as {found_sig}")
}; };
diag.subdiagnostic(FnConsiderCasting { casting }); diag.subdiagnostic(self.dcx(), FnConsiderCasting { casting });
} }
_ => { _ => {
return; return;
@ -822,7 +823,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
let diag = self.consider_returning_binding_diag(blk, expected_ty); let diag = self.consider_returning_binding_diag(blk, expected_ty);
match diag { match diag {
Some(diag) => { Some(diag) => {
err.subdiagnostic(diag); err.subdiagnostic(self.dcx(), diag);
true true
} }
None => false, None => false,

View file

@ -259,7 +259,7 @@ pub struct Linker {
impl Linker { impl Linker {
pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> {
let (codegen_results, work_products) = let (codegen_results, work_products) =
codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames)?; codegen_backend.join_codegen(self.ongoing_codegen, sess, &self.output_filenames);
sess.compile_status()?; sess.compile_status()?;

View file

@ -1757,7 +1757,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
diag.note(note.to_string()); diag.note(note.to_string());
} }
if let Some(sugg) = self.suggestion { if let Some(sugg) = self.suggestion {
diag.subdiagnostic(sugg); diag.subdiagnostic(diag.dcx, sugg);
} }
} }

View file

@ -331,44 +331,7 @@ impl DiagnosticDeriveVariantBuilder {
} }
} }
(Meta::Path(_), "subdiagnostic") => { (Meta::Path(_), "subdiagnostic") => {
if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { return Ok(quote! { diag.subdiagnostic(diag.dcx, #binding); });
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); });
} }
_ => (), _ => (),
} }

View file

@ -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()); let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some());
if !is_empty_match && all_arms_have_guards { if !is_empty_match && all_arms_have_guards {
err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded); err.subdiagnostic(cx.tcx.dcx(), NonExhaustiveMatchAllArmsGuarded);
} }
if let Some((span, sugg)) = suggestion { if let Some((span, sugg)) = suggestion {
err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders); err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);

View file

@ -270,7 +270,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) {
diag.span_label(self.yield_sp, fluent::_subdiag::label); diag.span_label(self.yield_sp, fluent::_subdiag::label);
if let Some(reason) = self.reason { if let Some(reason) = self.reason {
diag.subdiagnostic(reason); diag.subdiagnostic(diag.dcx, reason);
} }
diag.span_help(self.src_sp, fluent::_subdiag::help); diag.span_help(self.src_sp, fluent::_subdiag::help);
diag.arg("pre", self.pre); diag.arg("pre", self.pre);

View file

@ -452,7 +452,6 @@ impl<'a> Parser<'a> {
let mut expected = self let mut expected = self
.expected_tokens .expected_tokens
.iter() .iter()
.cloned()
.filter(|token| { .filter(|token| {
// Filter out suggestions that suggest the same token which was found and deemed incorrect. // Filter out suggestions that suggest the same token which was found and deemed incorrect.
fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool {
@ -464,7 +463,7 @@ impl<'a> Parser<'a> {
false false
} }
if *token != parser::TokenType::Token(self.token.kind.clone()) { if **token != parser::TokenType::Token(self.token.kind.clone()) {
let eq = is_ident_eq_keyword(&self.token.kind, &token); let eq = is_ident_eq_keyword(&self.token.kind, &token);
// If the suggestion is a keyword and the found token is an ident, // If the suggestion is a keyword and the found token is an ident,
// the content of which are equal to the suggestion's content, // the content of which are equal to the suggestion's content,
@ -483,6 +482,7 @@ impl<'a> Parser<'a> {
} }
false false
}) })
.cloned()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
expected.sort_by_cached_key(|x| x.to_string()); expected.sort_by_cached_key(|x| x.to_string());
expected.dedup(); expected.dedup();
@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> {
let mut err = self.dcx().struct_span_err(span, msg); let mut err = self.dcx().struct_span_err(span, msg);
let sp = self.sess.source_map().start_point(self.token.span); let sp = self.sess.source_map().start_point(self.token.span);
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { 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"); err.span_label(span, "expected expression");

View file

@ -1433,7 +1433,7 @@ impl<'a> Parser<'a> {
// If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }`
// then suggest parens around the lhs. // then suggest parens around the lhs.
if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { 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 err
}) })

View file

@ -1933,7 +1933,7 @@ impl<'a> Parser<'a> {
if self.token.kind == token::Not { if self.token.kind == token::Not {
if let Err(mut err) = self.unexpected::<FieldDef>() { if let Err(mut err) = self.unexpected::<FieldDef>() {
// Encounter the macro invocation // Encounter the macro invocation
err.subdiagnostic(MacroExpandsToAdtField { adt_ty }); err.subdiagnostic(self.dcx(), MacroExpandsToAdtField { adt_ty });
return Err(err); return Err(err);
} }
} }
@ -2352,10 +2352,13 @@ impl<'a> Parser<'a> {
.into_iter() .into_iter()
.any(|s| self.prev_token.is_ident_named(s)); .any(|s| self.prev_token.is_ident_named(s));
err.subdiagnostic(errors::FnTraitMissingParen { err.subdiagnostic(
span: self.prev_token.span, self.dcx(),
machine_applicable, errors::FnTraitMissingParen {
}); span: self.prev_token.span,
machine_applicable,
},
);
} }
return Err(err); return Err(err);
} }

View file

@ -843,7 +843,7 @@ impl<'a> Parser<'a> {
let sp = self.sess.source_map().start_point(self.token.span); let sp = self.sess.source_map().start_point(self.token.span);
if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { 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) Err(err)

View file

@ -893,7 +893,7 @@ impl<'a> Parser<'a> {
ParseError { ParseError {
description: "expected format parameter to occur after `:`".to_owned(), description: "expected format parameter to occur after `:`".to_owned(),
note: None, note: None,
label: format!("expected `{}` to occur after `:`", alignment).to_owned(), label: format!("expected `{}` to occur after `:`", alignment),
span: pos.to(pos), span: pos.to(pos),
secondary_label: None, secondary_label: None,
suggestion: Suggestion::None, suggestion: Suggestion::None,

View file

@ -403,9 +403,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
if let Some(suggestion) = suggestion { if let Some(suggestion) = suggestion {
err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion }); err.subdiagnostic(
self.dcx(),
ChangeImportBindingSuggestion { span: binding_span, suggestion },
);
} else { } 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 { 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; return;
} }
if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { 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; return;
} }
if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
err.subdiagnostic(AddedMacroUse); err.subdiagnostic(self.dcx(), AddedMacroUse);
return; return;
} }
@ -1450,10 +1453,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let span = self.def_span(def_id); let span = self.def_span(def_id);
let source_map = self.tcx.sess.source_map(); let source_map = self.tcx.sess.source_map();
let head_span = source_map.guess_head_span(span); let head_span = source_map.guess_head_span(span);
err.subdiagnostic(ConsiderAddingADerive { err.subdiagnostic(
span: head_span.shrink_to_lo(), self.dcx(),
suggestion: "#[derive(Default)]\n".to_string(), ConsiderAddingADerive {
}); span: head_span.shrink_to_lo(),
suggestion: "#[derive(Default)]\n".to_string(),
},
);
} }
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(

View file

@ -1262,12 +1262,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// exclude decl_macro // exclude decl_macro
if self.get_macro_by_def_id(def_id).macro_rules => if self.get_macro_by_def_id(def_id).macro_rules =>
{ {
err.subdiagnostic(ConsiderAddingMacroExport { err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport {
span: binding.span, span: binding.span,
}); });
} }
_ => { _ => {
err.subdiagnostic(ConsiderMarkingAsPub { err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub {
span: import.span, span: import.span,
ident, ident,
}); });

View file

@ -1111,11 +1111,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
Side::Start => (segment.ident.span.between(range.span), " @ ".into()), Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
}; };
err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { err.subdiagnostic(
span, self.r.dcx(),
ident: segment.ident, errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
snippet, span,
}); ident: segment.ident,
snippet,
},
);
} }
enum Side { enum Side {
@ -1207,10 +1210,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}); });
if let Some(param) = param { if let Some(param) = param {
err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg { err.subdiagnostic(
span: param.shrink_to_lo(), self.r.dcx(),
applicability, errors::UnexpectedResChangeTyToConstParamSugg {
}); span: param.shrink_to_lo(),
applicability,
},
);
} }
} }

View file

@ -173,21 +173,21 @@ pub fn add_feature_diagnostics_for_issue(
feature_from_cli: bool, feature_from_cli: bool,
) { ) {
if let Some(n) = find_feature_issue(feature, issue) { 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 // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
if sess.parse_sess.unstable_features.is_nightly_build() { if sess.parse_sess.unstable_features.is_nightly_build() {
if feature_from_cli { if feature_from_cli {
err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature });
} else { } else {
err.subdiagnostic(FeatureDiagnosticHelp { feature }); err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature });
} }
if sess.opts.unstable_opts.ui_testing { 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() { } else if let Some(suggestion) = SuggestUpgradeCompiler::new() {
err.subdiagnostic(suggestion); err.subdiagnostic(sess.dcx(), suggestion);
} }
} }
} }

View file

@ -17,6 +17,7 @@ pub enum Arch {
Arm64e, Arm64e,
Arm64_32, Arm64_32,
I386, I386,
I386_sim,
I686, I686,
X86_64, X86_64,
X86_64h, X86_64h,
@ -34,7 +35,7 @@ impl Arch {
Arm64 | Arm64_macabi | Arm64_sim => "arm64", Arm64 | Arm64_macabi | Arm64_sim => "arm64",
Arm64e => "arm64e", Arm64e => "arm64e",
Arm64_32 => "arm64_32", Arm64_32 => "arm64_32",
I386 => "i386", I386 | I386_sim => "i386",
I686 => "i686", I686 => "i686",
X86_64 | X86_64_sim | X86_64_macabi => "x86_64", X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
X86_64h => "x86_64h", X86_64h => "x86_64h",
@ -45,7 +46,7 @@ impl Arch {
Cow::Borrowed(match self { Cow::Borrowed(match self {
Armv7k | Armv7s => "arm", Armv7k | Armv7s => "arm",
Arm64 | Arm64e | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64", Arm64 | Arm64e | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
I386 | I686 => "x86", I386 | I386_sim | I686 => "x86",
X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64", X86_64 | X86_64_sim | X86_64_macabi | X86_64h => "x86_64",
}) })
} }
@ -54,9 +55,7 @@ impl Arch {
match self { match self {
Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "", Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "",
X86_64_macabi | Arm64_macabi => "macabi", X86_64_macabi | Arm64_macabi => "macabi",
// x86_64-apple-ios is a simulator target, even though it isn't I386_sim | Arm64_sim | X86_64_sim => "sim",
// declared that way in the target like the other ones...
Arm64_sim | X86_64_sim => "sim",
} }
} }
@ -70,7 +69,7 @@ impl Arch {
// Only macOS 10.12+ is supported, which means // Only macOS 10.12+ is supported, which means
// all x86_64/x86 CPUs must be running at least penryn // all x86_64/x86 CPUs must be running at least penryn
// https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82 // https://github.com/llvm/llvm-project/blob/01f924d0e37a5deae51df0d77e10a15b63aa0c0f/clang/lib/Driver/ToolChains/Arch/X86.cpp#L79-L82
I386 | I686 => "penryn", I386 | I386_sim | I686 => "penryn",
X86_64 | X86_64_sim => "penryn", X86_64 | X86_64_sim => "penryn",
X86_64_macabi => "penryn", X86_64_macabi => "penryn",
// Note: `core-avx2` is slightly more advanced than `x86_64h`, see // Note: `core-avx2` is slightly more advanced than `x86_64h`, see
@ -85,7 +84,7 @@ impl Arch {
fn stack_probes(self) -> StackProbeType { fn stack_probes(self) -> StackProbeType {
match self { match self {
Armv7k | Armv7s => StackProbeType::None, Armv7k | Armv7s => StackProbeType::None,
Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h | X86_64_sim Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 | X86_64h | X86_64_sim
| X86_64_macabi | Arm64_macabi | Arm64_sim => StackProbeType::Inline, | X86_64_macabi | Arm64_macabi | Arm64_sim => StackProbeType::Inline,
} }
} }
@ -302,8 +301,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]>
// Otherwise if cross-compiling for a different OS/SDK, remove any part // Otherwise if cross-compiling for a different OS/SDK, remove any part
// of the linking environment that's wrong and reversed. // of the linking environment that's wrong and reversed.
match arch { match arch {
Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64
| X86_64h | Arm64_sim => { | X86_64_sim | X86_64h | Arm64_sim => {
cvs!["MACOSX_DEPLOYMENT_TARGET"] cvs!["MACOSX_DEPLOYMENT_TARGET"]
} }
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],

View file

@ -2,7 +2,9 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
use crate::spec::{Target, TargetOptions}; use crate::spec::{Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
let arch = Arch::I386; // i386-apple-ios is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
let arch = Arch::I386_sim;
Target { Target {
// Clang automatically chooses a more specific target based on // Clang automatically chooses a more specific target based on
// IPHONEOS_DEPLOYMENT_TARGET. // IPHONEOS_DEPLOYMENT_TARGET.

View file

@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch};
use crate::spec::{SanitizerSet, Target, TargetOptions}; use crate::spec::{SanitizerSet, Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
// x86_64-apple-ios is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
let arch = Arch::X86_64_sim; let arch = Arch::X86_64_sim;
let mut base = opts("ios", arch); let mut base = opts("ios", arch);
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD;

View file

@ -2,6 +2,8 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch};
use crate::spec::{Target, TargetOptions}; use crate::spec::{Target, TargetOptions};
pub fn target() -> Target { pub fn target() -> Target {
// x86_64-apple-tvos is a simulator target, even though it isn't declared
// that way in the target name like the other ones...
let arch = Arch::X86_64_sim; let arch = Arch::X86_64_sim;
Target { Target {
llvm_target: tvos_sim_llvm_target(arch).into(), llvm_target: tvos_sim_llvm_target(arch).into(),

View file

@ -223,8 +223,10 @@ impl<'tcx> InferCtxt<'tcx> {
goal: Goal<'tcx, ty::Predicate<'tcx>>, goal: Goal<'tcx, ty::Predicate<'tcx>>,
visitor: &mut V, visitor: &mut V,
) -> ControlFlow<V::BreakTy> { ) -> ControlFlow<V::BreakTy> {
let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); self.probe(|_| {
let proof_tree = proof_tree.unwrap(); let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes);
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) let proof_tree = proof_tree.unwrap();
visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree))
})
} }
} }

View file

@ -8,23 +8,21 @@ use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::InferOk; use crate::infer::InferOk;
use crate::regions::InferCtxtRegionExt; use crate::regions::InferCtxtRegionExt;
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt};
use crate::traits::engine::TraitEngineExt; use crate::traits::engine::TraitEngineExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::select::IntercrateAmbiguityCause;
use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::structural_normalize::StructurallyNormalizeExt;
use crate::traits::NormalizeExt; use crate::traits::NormalizeExt;
use crate::traits::SkipLeakCheck; use crate::traits::SkipLeakCheck;
use crate::traits::{ use crate::traits::{
Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext,
SelectionContext,
}; };
use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic; use rustc_errors::Diagnostic;
use rustc_hir::def::DefKind; use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::{util, TraitEngine}; use rustc_infer::traits::{util, TraitEngine, TraitEngineExt};
use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal}; use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::traits::specialization_graph::OverlapMode;
@ -310,29 +308,35 @@ fn equate_impl_headers<'tcx>(
fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>(
selcx: &mut SelectionContext<'cx, 'tcx>, selcx: &mut SelectionContext<'cx, 'tcx>,
obligations: &'a [PredicateObligation<'tcx>], obligations: &'a [PredicateObligation<'tcx>],
) -> Option<&'a PredicateObligation<'tcx>> { ) -> Option<PredicateObligation<'tcx>> {
let infcx = selcx.infcx; let infcx = selcx.infcx;
obligations.iter().find(|obligation| { if infcx.next_trait_solver() {
let evaluation_result = if infcx.next_trait_solver() { let mut fulfill_cx = FulfillmentCtxt::new(infcx);
infcx.evaluate_obligation(obligation) fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned());
} else {
// We only care about the obligations that are *definitely* true errors.
// Ambiguities do not prove the disjointness of two impls.
let mut errors = fulfill_cx.select_where_possible(infcx);
errors.pop().map(|err| err.obligation)
} else {
obligations.iter().cloned().find(|obligation| {
// We use `evaluate_root_obligation` to correctly track intercrate // We use `evaluate_root_obligation` to correctly track intercrate
// ambiguity clauses. We cannot use this in the new solver. // ambiguity clauses. We cannot use this in the new solver.
selcx.evaluate_root_obligation(obligation) let evaluation_result = selcx.evaluate_root_obligation(obligation);
};
match evaluation_result { match evaluation_result {
Ok(result) => !result.may_apply(), Ok(result) => !result.may_apply(),
// If overflow occurs, we need to conservatively treat the goal as possibly holding, // If overflow occurs, we need to conservatively treat the goal as possibly holding,
// since there can be instantiations of this goal that don't overflow and result in // since there can be instantiations of this goal that don't overflow and result in
// success. This isn't much of a problem in the old solver, since we treat overflow // success. This isn't much of a problem in the old solver, since we treat overflow
// fatally (this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>), // fatally (this still can be encountered: <https://github.com/rust-lang/rust/issues/105231>),
// but in the new solver, this is very important for correctness, since overflow // but in the new solver, this is very important for correctness, since overflow
// *must* be treated as ambiguity for completeness. // *must* be treated as ambiguity for completeness.
Err(_overflow) => false, Err(_overflow) => false,
} }
}) })
}
} }
/// Check if both impls can be satisfied by a common type by considering whether /// Check if both impls can be satisfied by a common type by considering whether
@ -522,15 +526,13 @@ fn try_prove_negated_where_clause<'tcx>(
// Without this, we over-eagerly register coherence ambiguity candidates when // Without this, we over-eagerly register coherence ambiguity candidates when
// impl candidates do exist. // impl candidates do exist.
let ref infcx = root_infcx.fork_with_intercrate(false); let ref infcx = root_infcx.fork_with_intercrate(false);
let ocx = ObligationCtxt::new(infcx); let mut fulfill_cx = FulfillmentCtxt::new(infcx);
ocx.register_obligation(Obligation::new( fulfill_cx.register_predicate_obligation(
infcx.tcx, infcx,
ObligationCause::dummy(), Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate),
param_env, );
negative_predicate, if !fulfill_cx.select_all_or_error(infcx).is_empty() {
));
if !ocx.select_all_or_error().is_empty() {
return false; return false;
} }

View file

@ -4558,11 +4558,14 @@ fn hint_missing_borrow<'tcx>(
} }
if !to_borrow.is_empty() { 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() { if !remove_borrow.is_empty() {
err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow }); err.subdiagnostic(
infcx.dcx(),
errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow },
);
} }
} }

View file

@ -485,10 +485,10 @@ impl<T, A: Allocator> VecDeque<T, A> {
// H := head // H := head
// L := last element (`self.to_physical_idx(self.len - 1)`) // L := last element (`self.to_physical_idx(self.len - 1)`)
// //
// H L // H L
// [o o o o o o o . ] // [o o o o o o o o ]
// H L // H L
// A [o o o o o o o . . . . . . . . . ] // A [o o o o o o o o . . . . . . . . ]
// L H // L H
// [o o o o o o o o ] // [o o o o o o o o ]
// H L // H L

View file

@ -11,7 +11,7 @@ use core::iter::{
TrustedRandomAccessNoCoerce, TrustedRandomAccessNoCoerce,
}; };
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
use core::num::NonZero; use core::num::NonZero;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use core::ops::Deref; use core::ops::Deref;
@ -200,27 +200,23 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
#[inline] #[inline]
fn next(&mut self) -> Option<T> { fn next(&mut self) -> Option<T> {
if T::IS_ZST { let ptr = if T::IS_ZST {
if self.ptr.as_ptr() == self.end as *mut _ { if self.ptr.as_ptr() == self.end as *mut T {
None return None;
} else {
// `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
// reducing the `end`.
self.end = self.end.wrapping_byte_sub(1);
// Make up a value of this ZST.
Some(unsafe { mem::zeroed() })
} }
// `ptr` has to stay where it is to remain aligned, so we reduce the length by 1 by
// reducing the `end`.
self.end = self.end.wrapping_byte_sub(1);
self.ptr
} else { } else {
if self.ptr == non_null!(self.end, T) { if self.ptr == non_null!(self.end, T) {
None return None;
} else {
let old = self.ptr;
self.ptr = unsafe { old.add(1) };
Some(unsafe { ptr::read(old.as_ptr()) })
} }
} let old = self.ptr;
self.ptr = unsafe { old.add(1) };
old
};
Some(unsafe { ptr.read() })
} }
#[inline] #[inline]
@ -305,7 +301,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
// Also note the implementation of `Self: TrustedRandomAccess` requires // Also note the implementation of `Self: TrustedRandomAccess` requires
// that `T: Copy` so reading elements from the buffer doesn't invalidate // that `T: Copy` so reading elements from the buffer doesn't invalidate
// them for `Drop`. // them for `Drop`.
unsafe { if T::IS_ZST { mem::zeroed() } else { self.ptr.add(i).read() } } unsafe { self.ptr.add(i).read() }
} }
} }
@ -314,23 +310,22 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
#[inline] #[inline]
fn next_back(&mut self) -> Option<T> { fn next_back(&mut self) -> Option<T> {
if T::IS_ZST { if T::IS_ZST {
if self.end as *mut _ == self.ptr.as_ptr() { if self.ptr.as_ptr() == self.end as *mut _ {
None return None;
} else {
// See above for why 'ptr.offset' isn't used
self.end = self.end.wrapping_byte_sub(1);
// Make up a value of this ZST.
Some(unsafe { mem::zeroed() })
} }
// See above for why 'ptr.offset' isn't used
self.end = self.end.wrapping_byte_sub(1);
// Note that even though this is next_back() we're reading from `self.ptr`, not
// `self.end`. We track our length using the byte offset from `self.ptr` to `self.end`,
// so the end pointer may not be suitably aligned for T.
Some(unsafe { ptr::read(self.ptr.as_ptr()) })
} else { } else {
if non_null!(self.end, T) == self.ptr { if self.ptr == non_null!(self.end, T) {
None return None;
} else { }
let new_end = unsafe { non_null!(self.end, T).sub(1) }; unsafe {
*non_null!(mut self.end, T) = new_end; self.end = self.end.sub(1);
Some(ptr::read(self.end))
Some(unsafe { ptr::read(new_end.as_ptr()) })
} }
} }
} }

View file

@ -11,9 +11,15 @@ use std::{
}; };
fn parse(config: &str) -> Config { fn parse(config: &str) -> Config {
Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| { let config = format!("{config} \r\n build.rustc = \"/does-not-exists\" ");
toml::from_str(config).unwrap() Config::parse_inner(
}) &[
"check".to_owned(),
"--config=/does/not/exist".to_owned(),
"--skip-stage0-validation".to_owned(),
],
|&_| toml::from_str(&config).unwrap(),
)
} }
#[test] #[test]

View file

@ -399,6 +399,7 @@ impl Config {
self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host))); self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host)));
} }
self.create(&clippy_stamp, date);
cargo_clippy cargo_clippy
} }

View file

@ -84,9 +84,9 @@ pub fn span_lint_and_help<T: LintContext>(
cx.span_lint(lint, span, msg.to_string(), |diag| { cx.span_lint(lint, span, msg.to_string(), |diag| {
let help = help.to_string(); let help = help.to_string();
if let Some(help_span) = help_span { if let Some(help_span) = help_span {
diag.span_help(help_span, help.to_string()); diag.span_help(help_span, help);
} else { } else {
diag.help(help.to_string()); diag.help(help);
} }
docs_link(diag, lint); docs_link(diag, lint);
}); });

View file

@ -505,7 +505,7 @@ pub fn report_msg<'tcx>(
let is_local = machine.is_local(frame_info); let is_local = machine.is_local(frame_info);
// No span for non-local frames and the first frame (which is the error site). // No span for non-local frames and the first frame (which is the error site).
if is_local && idx > 0 { 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 { } else {
let sm = sess.source_map(); let sm = sess.source_map();
let span = sm.span_to_embeddable_string(frame_info.span); let span = sm.span_to_embeddable_string(frame_info.span);

View file

@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::path::Path; use std::path::Path;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
@ -40,6 +41,16 @@ impl Translate for SilentEmitter {
fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle {
panic!("silent emitter attempted to translate a diagnostic"); 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 { impl Emitter for SilentEmitter {

View file

@ -32,9 +32,9 @@ pub fn vec_iter_is_empty_nonnull(it: &vec::IntoIter<u8>) -> bool {
it.is_empty() it.is_empty()
} }
// CHECK-LABEL: @vec_iter_next // CHECK-LABEL: @vec_iter_next_nonnull
#[no_mangle] #[no_mangle]
pub fn vec_iter_next(it: &mut vec::IntoIter<u8>) -> Option<u8> { pub fn vec_iter_next_nonnull(it: &mut vec::IntoIter<u8>) -> Option<u8> {
// CHECK: load ptr // CHECK: load ptr
// CHECK-SAME: !nonnull // CHECK-SAME: !nonnull
// CHECK-SAME: !noundef // CHECK-SAME: !noundef
@ -44,3 +44,16 @@ pub fn vec_iter_next(it: &mut vec::IntoIter<u8>) -> Option<u8> {
// CHECK: ret // CHECK: ret
it.next() it.next()
} }
// CHECK-LABEL: @vec_iter_next_back_nonnull
#[no_mangle]
pub fn vec_iter_next_back_nonnull(it: &mut vec::IntoIter<u8>) -> Option<u8> {
// CHECK: load ptr
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: load ptr
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: ret
it.next_back()
}

View file

@ -49,11 +49,11 @@ impl CodegenBackend for TheBackend {
ongoing_codegen: Box<dyn Any>, ongoing_codegen: Box<dyn Any>,
_sess: &Session, _sess: &Session,
_outputs: &OutputFilenames, _outputs: &OutputFilenames,
) -> Result<(CodegenResults, FxIndexMap<WorkProductId, WorkProduct>), ErrorGuaranteed> { ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
let codegen_results = ongoing_codegen let codegen_results = ongoing_codegen
.downcast::<CodegenResults>() .downcast::<CodegenResults>()
.expect("in join_codegen: ongoing_codegen is not a CodegenResults"); .expect("in join_codegen: ongoing_codegen is not a CodegenResults");
Ok((*codegen_results, FxIndexMap::default())) (*codegen_results, FxIndexMap::default())
} }
fn link( fn link(

View file

@ -701,7 +701,7 @@ struct RawIdentDiagnosticArg {
#[diag(no_crate_example)] #[diag(no_crate_example)]
struct SubdiagnosticBad { struct SubdiagnosticBad {
#[subdiagnostic(bad)] #[subdiagnostic(bad)]
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note, note: Note,
} }
@ -717,7 +717,7 @@ struct SubdiagnosticBadStr {
#[diag(no_crate_example)] #[diag(no_crate_example)]
struct SubdiagnosticBadTwice { struct SubdiagnosticBadTwice {
#[subdiagnostic(bad, bad)] #[subdiagnostic(bad, bad)]
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note, note: Note,
} }
@ -725,7 +725,7 @@ struct SubdiagnosticBadTwice {
#[diag(no_crate_example)] #[diag(no_crate_example)]
struct SubdiagnosticBadLitStr { struct SubdiagnosticBadLitStr {
#[subdiagnostic("bad")] #[subdiagnostic("bad")]
//~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note, note: Note,
} }
@ -739,8 +739,9 @@ struct SubdiagnosticEagerLint {
#[derive(Diagnostic)] #[derive(Diagnostic)]
#[diag(no_crate_example)] #[diag(no_crate_example)]
struct SubdiagnosticEagerCorrect { struct SubdiagnosticEagerFormerlyCorrect {
#[subdiagnostic(eager)] #[subdiagnostic(eager)]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
note: Note, note: Note,
} }
@ -761,6 +762,7 @@ pub(crate) struct SubdiagnosticWithSuggestion {
#[diag(no_crate_example)] #[diag(no_crate_example)]
struct SubdiagnosticEagerSuggestion { struct SubdiagnosticEagerSuggestion {
#[subdiagnostic(eager)] #[subdiagnostic(eager)]
//~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
sub: SubdiagnosticWithSuggestion, sub: SubdiagnosticWithSuggestion,
} }

View file

@ -468,11 +468,11 @@ LL | #[label]
| |
= help: `#[label]` and `#[suggestion]` can only be applied to fields = help: `#[label]` and `#[suggestion]` can only be applied to fields
error: `eager` is the only supported nested attribute for `subdiagnostic` error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:703:7 --> $DIR/diagnostic-derive.rs:703:5
| |
LL | #[subdiagnostic(bad)] LL | #[subdiagnostic(bad)]
| ^^^^^^^^^^^^^ | ^
error: `#[subdiagnostic = ...]` is not a valid attribute error: `#[subdiagnostic = ...]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:711:5 --> $DIR/diagnostic-derive.rs:711:5
@ -480,40 +480,50 @@ error: `#[subdiagnostic = ...]` is not a valid attribute
LL | #[subdiagnostic = "bad"] LL | #[subdiagnostic = "bad"]
| ^ | ^
error: `eager` is the only supported nested attribute for `subdiagnostic` error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:719:7 --> $DIR/diagnostic-derive.rs:719:5
| |
LL | #[subdiagnostic(bad, bad)] LL | #[subdiagnostic(bad, bad)]
| ^^^^^^^^^^^^^ | ^
error: `eager` is the only supported nested attribute for `subdiagnostic` error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:727:7 --> $DIR/diagnostic-derive.rs:727:5
| |
LL | #[subdiagnostic("bad")] LL | #[subdiagnostic("bad")]
| ^^^^^^^^^^^^^ | ^
error: `#[subdiagnostic(...)]` is not a valid attribute error: `#[subdiagnostic(...)]` is not a valid attribute
--> $DIR/diagnostic-derive.rs:735:5 --> $DIR/diagnostic-derive.rs:735:5
| |
LL | #[subdiagnostic(eager)] 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(...)` error: expected at least one string literal for `code(...)`
--> $DIR/diagnostic-derive.rs:793:23 --> $DIR/diagnostic-derive.rs:795:23
| |
LL | #[suggestion(code())] LL | #[suggestion(code())]
| ^ | ^
error: `code(...)` must contain only string literals error: `code(...)` must contain only string literals
--> $DIR/diagnostic-derive.rs:801:23 --> $DIR/diagnostic-derive.rs:803:23
| |
LL | #[suggestion(code(foo))] LL | #[suggestion(code(foo))]
| ^^^ | ^^^
error: `#[suggestion(...)]` is not a valid attribute 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 = "")] LL | #[suggestion(no_crate_suggestion, code = "")]
| ^ | ^
@ -529,13 +539,13 @@ LL | #[diag = "E0123"]
| ^ maybe a missing crate `core`? | ^ maybe a missing crate `core`?
error[E0433]: failed to resolve: 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))] LL | #[suggestion(code(foo))]
| ^^^ maybe a missing crate `core`? | ^^^ maybe a missing crate `core`?
error[E0433]: failed to resolve: 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)] LL | #[suggestion(code = 3)]
| ^ maybe a missing crate `core`? | ^ maybe a missing crate `core`?
@ -601,7 +611,7 @@ LL | #[diag(nonsense, code = E0123)]
| ^^^^^^^^ not found in `crate::fluent_generated` | ^^^^^^^^ not found in `crate::fluent_generated`
error[E0425]: cannot find value `__code_34` in this scope 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)] LL | #[derive(Diagnostic)]
| ^^^^^^^^^^ not found in this scope | ^^^^^^^^^^ 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 --> $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) = 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. Some errors have detailed explanations: E0277, E0425, E0433.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0277`.

View file

@ -0,0 +1,20 @@
//@ compile-flags: -Znext-solver=coherence
//@ check-pass
trait Mirror {
type Assoc;
}
impl<T> Mirror for T {
type Assoc = T;
}
trait Foo {}
trait Bar {}
// self type starts out as `?0` but is constrained to `()`
// due to the where clause below. Because `(): Bar` does not
// hold in intercrate mode, we can prove the impls disjoint.
impl<T> Foo for T where (): Mirror<Assoc = T> {}
impl<T> Foo for T where T: Bar {}
fn main() {}

View file

@ -0,0 +1,22 @@
//@ compile-flags: -Znext-solver=coherence
trait Mirror {
type Assoc;
}
impl<T> Mirror for T {
type Assoc = T;
}
trait Foo {}
// Even though using fulfillment in coherence allows us to figure out that
// `?T = ()`, we still treat it as incoherent because `(): Iterator` may be
// added upstream.
impl<T> Foo for T where (): Mirror<Assoc = T> {}
//~^ NOTE first implementation here
impl<T> Foo for T where T: Iterator {}
//~^ ERROR conflicting implementations of trait `Foo` for type `()`
//~| NOTE conflicting implementation for `()`
//~| NOTE upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0119]: conflicting implementations of trait `Foo` for type `()`
--> $DIR/incoherent-even-though-we-fulfill.rs:17:1
|
LL | impl<T> Foo for T where (): Mirror<Assoc = T> {}
| --------------------------------------------- first implementation here
LL |
LL | impl<T> Foo for T where T: Iterator {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
= note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0119`.