From 0925ff8300ed724f1a1760c0bedd7522f49b3203 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Wed, 14 Feb 2024 19:10:49 +0300 Subject: [PATCH 01/10] use build.rustc config and skip-stage0-validation flag This change helps us to bypass downloading the beta compiler in bootstrap tests. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/tests.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index 0ae466eca7d7c..6ac573c68df18 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -11,9 +11,15 @@ use std::{ }; fn parse(config: &str) -> Config { - Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], |&_| { - toml::from_str(config).unwrap() - }) + let config = format!("{config} \r\n build.rustc = \"/does-not-exists\" "); + Config::parse_inner( + &[ + "check".to_owned(), + "--config=/does/not/exist".to_owned(), + "--skip-stage0-validation".to_owned(), + ], + |&_| toml::from_str(&config).unwrap(), + ) } #[test] From b80fc5d4e8ce95a00b14a50e8ee0561b64736480 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 14 Feb 2024 14:17:27 +0000 Subject: [PATCH 02/10] errors: only eagerly translate subdiagnostics Subdiagnostics don't need to be lazily translated, they can always be eagerly translated. Eager translation is slightly more complex as we need to have a `DiagCtxt` available to perform the translation, which involves slightly more threading of that context. This slight increase in complexity should enable later simplifications - like passing `DiagCtxt` into `AddToDiagnostic` and moving Fluent messages into the diagnostic structs rather than having them in separate files (working on that was what led to this change). Signed-off-by: David Wood --- .../src/diagnostics/conflict_errors.rs | 89 +++++--- .../rustc_borrowck/src/diagnostics/mod.rs | 202 +++++++++++------- .../src/diagnostics/move_errors.rs | 47 ++-- .../src/diagnostics/mutability_errors.rs | 2 +- .../src/diagnostics/region_errors.rs | 10 +- compiler/rustc_codegen_gcc/src/errors.rs | 2 +- compiler/rustc_codegen_llvm/src/errors.rs | 2 +- .../src/transform/check_consts/ops.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 36 ++-- compiler/rustc_errors/src/diagnostic.rs | 11 +- .../rustc_errors/src/diagnostic_builder.rs | 3 - compiler/rustc_errors/src/emitter.rs | 23 ++ compiler/rustc_errors/src/lib.rs | 71 ++++-- compiler/rustc_errors/src/translation.rs | 4 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 15 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 2 +- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_hir_typeck/src/cast.rs | 24 ++- compiler/rustc_hir_typeck/src/expr.rs | 7 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 96 +++++---- .../rustc_hir_typeck/src/method/suggest.rs | 27 +-- compiler/rustc_hir_typeck/src/op.rs | 2 +- .../src/infer/error_reporting/mod.rs | 4 +- .../src/infer/error_reporting/note.rs | 2 +- .../src/infer/error_reporting/suggest.rs | 33 +-- compiler/rustc_lint/src/lints.rs | 2 +- .../src/diagnostics/diagnostic_builder.rs | 39 +--- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_mir_transform/src/errors.rs | 2 +- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 13 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_resolve/src/diagnostics.rs | 24 ++- compiler/rustc_resolve/src/imports.rs | 4 +- .../rustc_resolve/src/late/diagnostics.rs | 24 ++- compiler/rustc_session/src/parse.rs | 10 +- .../src/traits/error_reporting/suggestions.rs | 7 +- src/tools/miri/src/diagnostics.rs | 2 +- src/tools/rustfmt/src/parse/session.rs | 11 + .../session-diagnostic/diagnostic-derive.rs | 10 +- .../diagnostic-derive.stderr | 44 ++-- 43 files changed, 532 insertions(+), 388 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 18cf6f64fbc03..2b0c0e939f59b 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -229,7 +229,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { seen_spans.insert(move_span); } - use_spans.var_path_only_subdiag(&mut err, desired_action); + use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action); if !is_loop_move { err.span_label( @@ -291,18 +291,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if needs_note { if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move, - ty, - place: ¬e_msg, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move, + ty, + place: ¬e_msg, + span, + }, + ); } else { - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { - is_partial_move, - ty, - place: ¬e_msg, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Note { + is_partial_move, + ty, + place: ¬e_msg, + }, + ); }; } @@ -557,7 +563,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { E0381, "{used} binding {desc}{isnt_initialized}" ); - use_spans.var_path_only_subdiag(&mut err, desired_action); + use_spans.var_path_only_subdiag(self.dcx(), &mut err, desired_action); if let InitializationRequiringAction::PartialAssignment | InitializationRequiringAction::Assignment = desired_action @@ -848,9 +854,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &value_msg, ); - borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); + borrow_spans.var_path_only_subdiag( + self.dcx(), + &mut err, + crate::InitializationRequiringAction::Borrow, + ); - move_spans.var_subdiag(None, &mut err, None, |kind, var_span| { + move_spans.var_subdiag(self.dcx(), &mut err, None, |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => MoveUseInCoroutine { var_span }, @@ -895,7 +905,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_subdiag(None, &mut err, Some(borrow.kind), |kind, var_span| { + borrow_spans.var_subdiag(self.dcx(), &mut err, Some(borrow.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; let place = &borrow.borrowed_place; let desc_place = self.describe_any_place(place.as_ref()); @@ -1043,7 +1053,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "mutably borrow", ); borrow_spans.var_subdiag( - None, + self.dcx(), &mut err, Some(BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture }), |kind, var_span| { @@ -1131,22 +1141,31 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if issued_spans == borrow_spans { - borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { - use crate::session_diagnostics::CaptureVarCause::*; - match kind { - hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine { - place: desc_place, - var_span, - is_single_var: false, - }, - hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { - BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } + borrow_spans.var_subdiag( + self.dcx(), + &mut err, + Some(gen_borrow_kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + hir::ClosureKind::Coroutine(_) => BorrowUsePlaceCoroutine { + place: desc_place, + var_span, + is_single_var: false, + }, + hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { + BorrowUsePlaceClosure { + place: desc_place, + var_span, + is_single_var: false, + } + } } - } - }); + }, + ); } else { issued_spans.var_subdiag( - Some(self.dcx()), + self.dcx(), &mut err, Some(issued_borrow.kind), |kind, var_span| { @@ -1165,7 +1184,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); borrow_spans.var_subdiag( - Some(self.dcx()), + self.dcx(), &mut err, Some(gen_borrow_kind), |kind, var_span| { @@ -2217,7 +2236,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, format!("`{name}` dropped here while still borrowed")); - borrow_spans.args_subdiag(&mut err, |args_span| { + borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { is_within: borrow_spans.for_coroutine(), args_span, @@ -2476,7 +2495,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); - borrow_spans.args_subdiag(&mut err, |args_span| { + borrow_spans.args_subdiag(self.dcx(), &mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { is_within: borrow_spans.for_coroutine(), args_span, @@ -2935,7 +2954,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "assign", ); - loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, @@ -2953,7 +2972,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + loan_spans.var_subdiag(self.dcx(), &mut err, Some(loan.kind), |kind, var_span| { use crate::session_diagnostics::CaptureVarCause::*; match kind { hir::ClosureKind::Coroutine(_) => BorrowUseInCoroutine { var_span }, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 59f3aa706edea..4ca854c857de9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -124,7 +124,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.eager_subdiagnostic( + diag.subdiagnostic( self.dcx(), OnClosureNote::InvokedTwice { place_name: &ty::place_to_string_for_capture( @@ -146,7 +146,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind() { let did = did.expect_local(); if let Some((span, hir_place)) = self.infcx.tcx.closure_kind_origin(did) { - diag.eager_subdiagnostic( + diag.subdiagnostic( self.dcx(), OnClosureNote::MovedTwice { place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), @@ -587,11 +587,12 @@ impl UseSpans<'_> { /// Add a span label to the arguments of the closure, if it exists. pub(super) fn args_subdiag( self, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, f: impl FnOnce(Span) -> CaptureArgLabel, ) { if let UseSpans::ClosureUse { args_span, .. } = self { - err.subdiagnostic(f(args_span)); + err.subdiagnostic(dcx, f(args_span)); } } @@ -599,6 +600,7 @@ impl UseSpans<'_> { /// only adds label to the `path_span` pub(super) fn var_path_only_subdiag( self, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, action: crate::InitializationRequiringAction, ) { @@ -607,20 +609,26 @@ impl UseSpans<'_> { if let UseSpans::ClosureUse { closure_kind, path_span, .. } = self { match closure_kind { hir::ClosureKind::Coroutine(_) => { - err.subdiagnostic(match action { - Borrow => BorrowInCoroutine { path_span }, - MatchOn | Use => UseInCoroutine { path_span }, - Assignment => AssignInCoroutine { path_span }, - PartialAssignment => AssignPartInCoroutine { path_span }, - }); + err.subdiagnostic( + dcx, + match action { + Borrow => BorrowInCoroutine { path_span }, + MatchOn | Use => UseInCoroutine { path_span }, + Assignment => AssignInCoroutine { path_span }, + PartialAssignment => AssignPartInCoroutine { path_span }, + }, + ); } hir::ClosureKind::Closure | hir::ClosureKind::CoroutineClosure(_) => { - err.subdiagnostic(match action { - Borrow => BorrowInClosure { path_span }, - MatchOn | Use => UseInClosure { path_span }, - Assignment => AssignInClosure { path_span }, - PartialAssignment => AssignPartInClosure { path_span }, - }); + err.subdiagnostic( + dcx, + match action { + Borrow => BorrowInClosure { path_span }, + MatchOn | Use => UseInClosure { path_span }, + Assignment => AssignInClosure { path_span }, + PartialAssignment => AssignPartInClosure { path_span }, + }, + ); } } } @@ -629,32 +637,32 @@ impl UseSpans<'_> { /// Add a subdiagnostic to the use of the captured variable, if it exists. pub(super) fn var_subdiag( self, - dcx: Option<&rustc_errors::DiagCtxt>, + dcx: &rustc_errors::DiagCtxt, err: &mut Diagnostic, kind: Option, f: impl FnOnce(hir::ClosureKind, Span) -> CaptureVarCause, ) { if let UseSpans::ClosureUse { closure_kind, capture_kind_span, path_span, .. } = self { if capture_kind_span != path_span { - err.subdiagnostic(match kind { - Some(kd) => match kd { - rustc_middle::mir::BorrowKind::Shared - | rustc_middle::mir::BorrowKind::Fake => { - CaptureVarKind::Immut { kind_span: capture_kind_span } - } + err.subdiagnostic( + dcx, + match kind { + Some(kd) => match kd { + rustc_middle::mir::BorrowKind::Shared + | rustc_middle::mir::BorrowKind::Fake => { + CaptureVarKind::Immut { kind_span: capture_kind_span } + } - rustc_middle::mir::BorrowKind::Mut { .. } => { - CaptureVarKind::Mut { kind_span: capture_kind_span } - } + rustc_middle::mir::BorrowKind::Mut { .. } => { + CaptureVarKind::Mut { kind_span: capture_kind_span } + } + }, + None => CaptureVarKind::Move { kind_span: capture_kind_span }, }, - None => CaptureVarKind::Move { kind_span: capture_kind_span }, - }); + ); }; let diag = f(closure_kind, path_span); - match dcx { - Some(hd) => err.eager_subdiagnostic(hd, diag), - None => err.subdiagnostic(diag), - }; + err.subdiagnostic(dcx, diag); } } @@ -1025,26 +1033,33 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { CallKind::FnCall { fn_trait_id, .. } if Some(fn_trait_id) == self.infcx.tcx.lang_items().fn_once_trait() => { - err.subdiagnostic(CaptureReasonLabel::Call { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); - err.subdiagnostic(CaptureReasonNote::FnOnceMoveInCall { var_span }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::Call { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); + err.subdiagnostic(self.dcx(), CaptureReasonNote::FnOnceMoveInCall { var_span }); } CallKind::Operator { self_arg, .. } => { let self_arg = self_arg.unwrap(); - err.subdiagnostic(CaptureReasonLabel::OperatorUse { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::OperatorUse { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); if self.fn_self_span_reported.insert(fn_span) { - err.subdiagnostic(CaptureReasonNote::LhsMoveByOperator { - span: self_arg.span, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonNote::LhsMoveByOperator { span: self_arg.span }, + ); } } CallKind::Normal { self_arg, desugaring, method_did, method_args } => { @@ -1061,11 +1076,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); let func = tcx.def_path_str(method_did); - err.subdiagnostic(CaptureReasonNote::FuncTakeSelf { - func, - place_name: place_name.clone(), - span: self_arg.span, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonNote::FuncTakeSelf { + func, + place_name: place_name.clone(), + span: self_arg.span, + }, + ); } let parent_did = tcx.parent(method_did); let parent_self_ty = @@ -1079,7 +1097,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { matches!(tcx.get_diagnostic_name(def_id), Some(sym::Option | sym::Result)) }); if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.subdiagnostic(CaptureReasonLabel::BorrowContent { var_span }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::BorrowContent { var_span }, + ); } if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { let ty = moved_place.ty(self.body, tcx).ty; @@ -1093,18 +1114,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => false, }; if suggest { - err.subdiagnostic(CaptureReasonSuggest::IterateSlice { - ty, - span: move_span.shrink_to_lo(), - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonSuggest::IterateSlice { + ty, + span: move_span.shrink_to_lo(), + }, + ); } - err.subdiagnostic(CaptureReasonLabel::ImplicitCall { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::ImplicitCall { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); // If the moved place was a `&mut` ref, then we can // suggest to reborrow it where it was moved, so it // will still be valid by the time we get to the usage. @@ -1128,19 +1155,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { if let Some((CallDesugaringKind::Await, _)) = desugaring { - err.subdiagnostic(CaptureReasonLabel::Await { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::Await { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); } else { - err.subdiagnostic(CaptureReasonLabel::MethodCall { - fn_call_span, - place_name: &place_name, - is_partial, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::MethodCall { + fn_call_span, + place_name: &place_name, + is_partial, + is_loop_message, + }, + ); } // Erase and shadow everything that could be passed to the new infcx. let ty = moved_place.ty(self.body, tcx).ty; @@ -1155,7 +1188,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) && self.infcx.can_eq(self.param_env, ty, self_ty) { - err.eager_subdiagnostic( + err.subdiagnostic( self.dcx(), CaptureReasonSuggest::FreshReborrow { span: move_span.shrink_to_hi(), @@ -1239,17 +1272,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { if move_span != span || is_loop_message { - err.subdiagnostic(CaptureReasonLabel::MovedHere { - move_span, - is_partial, - is_move_msg, - is_loop_message, - }); + err.subdiagnostic( + self.dcx(), + CaptureReasonLabel::MovedHere { + move_span, + is_partial, + is_move_msg, + is_loop_message, + }, + ); } // If the move error occurs due to a loop, don't show // another message for the same span if !is_loop_message { - move_spans.var_subdiag(None, err, None, |kind, var_span| match kind { + move_spans.var_subdiag(self.dcx(), err, None, |kind, var_span| match kind { hir::ClosureKind::Coroutine(_) => { CaptureVarCause::PartialMoveUseInCoroutine { var_span, is_partial } } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 126a50c91b494..dad20690d02cc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -448,12 +448,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => "value".to_string(), }; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: place_ty, - place: &place_desc, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }, + ); } else { binds_to.sort(); binds_to.dedup(); @@ -475,14 +478,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: place_ty, - place: &place_desc, - span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }, + ); - use_spans.args_subdiag(err, |args_span| { + use_spans.args_subdiag(self.dcx(), err, |args_span| { crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { place: place_desc, args_span, @@ -580,12 +586,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if binds_to.len() == 1 { let place_desc = &format!("`{}`", self.local_names[*local].unwrap()); - err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { - is_partial_move: false, - ty: bind_to.ty, - place: place_desc, - span: binding_span, - }); + err.subdiagnostic( + self.dcx(), + crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: bind_to.ty, + place: place_desc, + span: binding_span, + }, + ); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index b3d684086c286..5e659a5f3c239 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if suggest { borrow_spans.var_subdiag( - None, + self.dcx(), &mut err, Some(mir::BorrowKind::Mut { kind: mir::MutBorrowKind::Default }), |_kind, var_span| { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 7529ec53a9869..e8effd5c1633a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -616,13 +616,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let upvars_map = self.infcx.tcx.upvars_mentioned(def_id).unwrap(); let upvar_def_span = self.infcx.tcx.hir().span(def_hir); let upvar_span = upvars_map.get(&def_hir).unwrap().span; - diag.subdiagnostic(VarHereDenote::Defined { span: upvar_def_span }); - diag.subdiagnostic(VarHereDenote::Captured { span: upvar_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::Defined { span: upvar_def_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::Captured { span: upvar_span }); } } if let Some(fr_span) = self.give_region_a_name(*outlived_fr).unwrap().span() { - diag.subdiagnostic(VarHereDenote::FnMutInferred { span: fr_span }); + diag.subdiagnostic(self.dcx(), VarHereDenote::FnMutInferred { span: fr_span }); } self.suggest_move_on_borrowing_closure(&mut diag); @@ -788,7 +788,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }, }; - diag.subdiagnostic(err_category); + diag.subdiagnostic(self.dcx(), err_category); self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr); self.suggest_adding_lifetime_params(&mut diag, *fr, *outlived_fr); @@ -979,7 +979,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ident.span, "calling this method introduces the `impl`'s `'static` requirement", ); - err.subdiagnostic(RequireStaticErr::UsedImpl { multi_span }); + err.subdiagnostic(self.dcx(), RequireStaticErr::UsedImpl { multi_span }); err.span_suggestion_verbose( span.shrink_to_hi(), "consider relaxing the implicit `'static` requirement", diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs index cc0fbe46dcc11..79eb4406b8a33 100644 --- a/compiler/rustc_codegen_gcc/src/errors.rs +++ b/compiler/rustc_codegen_gcc/src/errors.rs @@ -122,7 +122,7 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl diag.span(span); }; if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); + diag.subdiagnostic(dcx, missing_features); } diag.arg("features", self.features.join(", ")); diag diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 587c5e9e8d235..87e3774068bcd 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -131,7 +131,7 @@ impl IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnabl diag.span(span); }; if let Some(missing_features) = self.missing_features { - diag.subdiagnostic(missing_features); + diag.subdiagnostic(dcx, missing_features); } diag.arg("features", self.features.join(", ")); diag diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index 0c93cfaa54647..25ddd5e85f9f3 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -131,7 +131,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { // FIXME(effects) revisit this if !tcx.is_const_trait_impl_raw(data.impl_def_id) { let span = tcx.def_span(data.impl_def_id); - err.subdiagnostic(errors::NonConstImplNote { span }); + err.subdiagnostic(tcx.dcx(), errors::NonConstImplNote { span }); } } } diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index a1abe8fd4f306..f91b6655f6399 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -263,14 +263,10 @@ pub enum SubdiagnosticMessage { /// Translatable message which has already been translated eagerly. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would - /// be instantiated multiple times with different values. As translation normally happens - /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, - /// the setting of diagnostic arguments in the derived code will overwrite previous variable - /// values and only the final value will be set when translation occurs - resulting in - /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic - /// happening immediately after the subdiagnostic derive's logic has been run. This variant - /// stores messages which have been translated eagerly. - Eager(Cow<'static, str>), + /// be instantiated multiple times with different values. These subdiagnostics' messages + /// are translated when they are added to the parent diagnostic, producing this variant of + /// `DiagnosticMessage`. + Translated(Cow<'static, str>), /// Identifier of a Fluent message. Instances of this variant are generated by the /// `Subdiagnostic` derive. FluentIdentifier(FluentId), @@ -307,19 +303,15 @@ impl From> for SubdiagnosticMessage { pub enum DiagnosticMessage { /// Non-translatable diagnostic message. Str(Cow<'static, str>), - /// Translatable message which has already been translated eagerly. + /// Translatable message which has been already translated. /// /// Some diagnostics have repeated subdiagnostics where the same interpolated variables would - /// be instantiated multiple times with different values. As translation normally happens - /// immediately prior to emission, after the diagnostic and subdiagnostic derive logic has run, - /// the setting of diagnostic arguments in the derived code will overwrite previous variable - /// values and only the final value will be set when translation occurs - resulting in - /// incorrect diagnostics. Eager translation results in translation for a subdiagnostic - /// happening immediately after the subdiagnostic derive's logic has been run. This variant - /// stores messages which have been translated eagerly. - Eager(Cow<'static, str>), + /// be instantiated multiple times with different values. These subdiagnostics' messages + /// are translated when they are added to the parent diagnostic, producing this variant of + /// `DiagnosticMessage`. + Translated(Cow<'static, str>), /// Identifier for a Fluent message (with optional attribute) corresponding to the diagnostic - /// message. + /// message. Yet to be translated. /// /// /// @@ -336,7 +328,7 @@ impl DiagnosticMessage { pub fn with_subdiagnostic_message(&self, sub: SubdiagnosticMessage) -> Self { let attr = match sub { SubdiagnosticMessage::Str(s) => return DiagnosticMessage::Str(s), - SubdiagnosticMessage::Eager(s) => return DiagnosticMessage::Eager(s), + SubdiagnosticMessage::Translated(s) => return DiagnosticMessage::Translated(s), SubdiagnosticMessage::FluentIdentifier(id) => { return DiagnosticMessage::FluentIdentifier(id, None); } @@ -345,7 +337,7 @@ impl DiagnosticMessage { match self { DiagnosticMessage::Str(s) => DiagnosticMessage::Str(s.clone()), - DiagnosticMessage::Eager(s) => DiagnosticMessage::Eager(s.clone()), + DiagnosticMessage::Translated(s) => DiagnosticMessage::Translated(s.clone()), DiagnosticMessage::FluentIdentifier(id, _) => { DiagnosticMessage::FluentIdentifier(id.clone(), Some(attr)) } @@ -354,7 +346,7 @@ impl DiagnosticMessage { pub fn as_str(&self) -> Option<&str> { match self { - DiagnosticMessage::Eager(s) | DiagnosticMessage::Str(s) => Some(s), + DiagnosticMessage::Translated(s) | DiagnosticMessage::Str(s) => Some(s), DiagnosticMessage::FluentIdentifier(_, _) => None, } } @@ -396,7 +388,7 @@ impl Into for DiagnosticMessage { fn into(self) -> SubdiagnosticMessage { match self { DiagnosticMessage::Str(s) => SubdiagnosticMessage::Str(s), - DiagnosticMessage::Eager(s) => SubdiagnosticMessage::Eager(s), + DiagnosticMessage::Translated(s) => SubdiagnosticMessage::Translated(s), DiagnosticMessage::FluentIdentifier(id, None) => { SubdiagnosticMessage::FluentIdentifier(id) } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index b14a12175c79b..d31321b48d007 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -851,18 +851,11 @@ impl Diagnostic { self } - /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see - /// [rustc_macros::Subdiagnostic]). - pub fn subdiagnostic(&mut self, subdiagnostic: impl AddToDiagnostic) -> &mut Self { - subdiagnostic.add_to_diagnostic(self); - self - } - /// Add a subdiagnostic from a type that implements `Subdiagnostic` (see /// [rustc_macros::Subdiagnostic]). Performs eager translation of any translatable messages /// used in the subdiagnostic, so suitable for use with repeated messages (i.e. re-use of /// interpolated variables). - pub fn eager_subdiagnostic( + pub fn subdiagnostic( &mut self, dcx: &crate::DiagCtxt, subdiagnostic: impl AddToDiagnostic, @@ -921,7 +914,7 @@ impl Diagnostic { /// Helper function that takes a `SubdiagnosticMessage` and returns a `DiagnosticMessage` by /// combining it with the primary message of the diagnostic (if translatable, otherwise it just /// passes the user's string along). - fn subdiagnostic_message_to_diagnostic_message( + pub(crate) fn subdiagnostic_message_to_diagnostic_message( &self, attr: impl Into, ) -> DiagnosticMessage { diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index e484bef0e0bc9..0572df69ca947 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -404,9 +404,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { name: impl Into>, arg: impl IntoDiagnosticArg, )); forward!((subdiagnostic, with_subdiagnostic)( - subdiagnostic: impl crate::AddToDiagnostic, - )); - forward!((eager_subdiagnostic, with_eager_subdiagnostic)( dcx: &DiagCtxt, subdiagnostic: impl crate::AddToDiagnostic, )); diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 38c6661377b19..00b7c50ad17d3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -10,6 +10,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::{FileLines, FileName, SourceFile, Span}; +use crate::error::TranslateError; use crate::snippet::{ Annotation, AnnotationColumn, AnnotationType, Line, MultilineAnnotation, Style, StyledString, }; @@ -559,6 +560,18 @@ pub struct SilentEmitter { pub fatal_note: String, } +pub fn silent_translate<'a>( + message: &'a DiagnosticMessage, +) -> Result, TranslateError<'_>> { + match message { + DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => Ok(Cow::Borrowed(msg)), + DiagnosticMessage::FluentIdentifier(identifier, _) => { + // Any value works here. + Ok(identifier.clone()) + } + } +} + impl Translate for SilentEmitter { fn fluent_bundle(&self) -> Option<&Lrc> { None @@ -567,6 +580,16 @@ impl Translate for SilentEmitter { fn fallback_fluent_bundle(&self) -> &FluentBundle { panic!("silent emitter attempted to translate message") } + + // Override `translate_message` for the silent emitter because eager translation of + // subdiagnostics result in a call to this. + fn translate_message<'a>( + &'a self, + message: &'a DiagnosticMessage, + _: &'a FluentArgs<'_>, + ) -> Result, TranslateError<'_>> { + silent_translate(message) + } } impl Emitter for SilentEmitter { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index b738ecb54ffc1..986e87cd2e2ce 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -640,7 +640,8 @@ impl DiagCtxt { message: DiagnosticMessage, args: impl Iterator>, ) -> SubdiagnosticMessage { - SubdiagnosticMessage::Eager(Cow::from(self.eagerly_translate_to_string(message, args))) + let inner = self.inner.borrow(); + inner.eagerly_translate(message, args) } /// Translate `message` eagerly with `args` to `String`. @@ -650,8 +651,7 @@ impl DiagCtxt { args: impl Iterator>, ) -> String { let inner = self.inner.borrow(); - let args = crate::translation::to_fluent_args(args); - inner.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() + inner.eagerly_translate_to_string(message, args) } // This is here to not allow mutation of flags; @@ -1446,6 +1446,25 @@ impl DiagCtxtInner { .or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } + /// Translate `message` eagerly with `args` to `SubdiagnosticMessage::Eager`. + pub fn eagerly_translate<'a>( + &self, + message: DiagnosticMessage, + args: impl Iterator>, + ) -> 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>, + ) -> String { + let args = crate::translation::to_fluent_args(args); + self.emitter.translate_message(&message, &args).map_err(Report::new).unwrap().to_string() + } + fn flush_delayed(&mut self) { if self.delayed_bugs.is_empty() { return; @@ -1484,15 +1503,22 @@ impl DiagCtxtInner { } let mut bug = - if backtrace || self.ice_file.is_none() { bug.decorate() } else { bug.inner }; + if backtrace || self.ice_file.is_none() { bug.decorate(self) } else { bug.inner }; // "Undelay" the delayed bugs (into plain `Bug`s). if bug.level != DelayedBug { // NOTE(eddyb) not panicking here because we're already producing // an ICE, and the more information the merrier. - bug.subdiagnostic(InvalidFlushedDelayedDiagnosticLevel { + let subdiag = InvalidFlushedDelayedDiagnosticLevel { span: bug.span.primary_span().unwrap(), level: bug.level, + }; + // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it + // just uses `DiagCtxtInner` functions. + subdiag.add_to_diagnostic_with(&mut bug, |diag, msg| { + let args = diag.args(); + let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); + self.eagerly_translate(msg, args) }); } bug.level = Bug; @@ -1527,25 +1553,35 @@ impl DelayedDiagnostic { DelayedDiagnostic { inner: diagnostic, note: backtrace } } - fn decorate(mut self) -> Diagnostic { + fn decorate(mut self, dcx: &DiagCtxtInner) -> Diagnostic { + // FIXME: Cannot use `Diagnostic::subdiagnostic` which takes `DiagCtxt`, but it + // just uses `DiagCtxtInner` functions. + let subdiag_with = |diag: &mut Diagnostic, msg| { + let args = diag.args(); + let msg = diag.subdiagnostic_message_to_diagnostic_message(msg); + dcx.eagerly_translate(msg, args) + }; + match self.note.status() { BacktraceStatus::Captured => { let inner = &self.inner; - self.inner.subdiagnostic(DelayedAtWithNewline { + let subdiag = DelayedAtWithNewline { span: inner.span.primary_span().unwrap_or(DUMMY_SP), emitted_at: inner.emitted_at.clone(), note: self.note, - }); + }; + subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); } // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. _ => { let inner = &self.inner; - self.inner.subdiagnostic(DelayedAtWithoutNewline { + let subdiag = DelayedAtWithoutNewline { span: inner.span.primary_span().unwrap_or(DUMMY_SP), emitted_at: inner.emitted_at.clone(), note: self.note, - }); + }; + subdiag.add_to_diagnostic_with(&mut self.inner, subdiag_with); } } @@ -1691,15 +1727,15 @@ impl Level { } // FIXME(eddyb) this doesn't belong here AFAICT, should be moved to callsite. -pub fn add_elided_lifetime_in_path_suggestion( +pub fn add_elided_lifetime_in_path_suggestion( source_map: &SourceMap, - diag: &mut Diagnostic, + diag: &mut DiagnosticBuilder<'_, E>, n: usize, path_span: Span, incl_angl_brckt: bool, insertion_span: Span, ) { - diag.subdiagnostic(ExpectedLifetimeParameter { span: path_span, count: n }); + diag.subdiagnostic(diag.dcx, ExpectedLifetimeParameter { span: path_span, count: n }); if !source_map.is_span_accessible(insertion_span) { // Do not try to suggest anything if generated by a proc-macro. return; @@ -1708,11 +1744,10 @@ pub fn add_elided_lifetime_in_path_suggestion( let suggestion = if incl_angl_brckt { format!("<{anon_lts}>") } else { format!("{anon_lts}, ") }; - diag.subdiagnostic(IndicateAnonymousLifetime { - span: insertion_span.shrink_to_hi(), - count: n, - suggestion, - }); + diag.subdiagnostic( + diag.dcx, + IndicateAnonymousLifetime { span: insertion_span.shrink_to_hi(), count: n, suggestion }, + ); } pub fn report_ambiguity_error<'a, G: EmissionGuarantee>( diff --git a/compiler/rustc_errors/src/translation.rs b/compiler/rustc_errors/src/translation.rs index 5bdac367d55e7..5f074dbbbad30 100644 --- a/compiler/rustc_errors/src/translation.rs +++ b/compiler/rustc_errors/src/translation.rs @@ -2,7 +2,7 @@ use crate::error::{TranslateError, TranslateErrorKind}; use crate::snippet::Style; use crate::{DiagnosticArg, DiagnosticMessage, FluentBundle}; use rustc_data_structures::sync::Lrc; -use rustc_error_messages::FluentArgs; +pub use rustc_error_messages::FluentArgs; use std::borrow::Cow; use std::env; use std::error::Report; @@ -61,7 +61,7 @@ pub trait Translate { ) -> Result, TranslateError<'_>> { trace!(?message, ?args); let (identifier, attr) = match message { - DiagnosticMessage::Str(msg) | DiagnosticMessage::Eager(msg) => { + DiagnosticMessage::Str(msg) | DiagnosticMessage::Translated(msg) => { return Ok(Cow::Borrowed(msg)); } DiagnosticMessage::FluentIdentifier(identifier, attr) => (identifier, attr), diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index eec86c36aedae..b3d370a9c8dec 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -7,7 +7,7 @@ use crate::mbe::{ use rustc_ast::token::{self, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; -use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; +use rustc_errors::{Applicability, DiagCtxt, Diagnostic, DiagnosticBuilder, DiagnosticMessage}; use rustc_parse::parser::{Parser, Recovery}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Ident; @@ -58,7 +58,7 @@ pub(super) fn failed_to_match_macro<'cx>( err.span_label(cx.source_map().guess_head_span(def_span), "when calling this macro"); } - annotate_doc_comment(&mut err, sess.source_map(), span); + annotate_doc_comment(cx.sess.dcx(), &mut err, sess.source_map(), span); if let Some(span) = remaining_matcher.span() { err.span_note(span, format!("while trying to match {remaining_matcher}")); @@ -311,12 +311,17 @@ enum ExplainDocComment { }, } -pub(super) fn annotate_doc_comment(err: &mut Diagnostic, sm: &SourceMap, span: Span) { +pub(super) fn annotate_doc_comment( + dcx: &DiagCtxt, + err: &mut Diagnostic, + sm: &SourceMap, + span: Span, +) { if let Ok(src) = sm.span_to_snippet(span) { if src.starts_with("///") || src.starts_with("/**") { - err.subdiagnostic(ExplainDocComment::Outer { span }); + err.subdiagnostic(dcx, ExplainDocComment::Outer { span }); } else if src.starts_with("//!") || src.starts_with("/*!") { - err.subdiagnostic(ExplainDocComment::Inner { span }); + err.subdiagnostic(dcx, ExplainDocComment::Inner { span }); } } } diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 83e0f870c8a25..c82609503c18a 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -454,7 +454,7 @@ pub fn compile_declarative_macro( let sp = token.span.substitute_dummy(def.span); let mut err = sess.dcx().struct_span_err(sp, s); err.span_label(sp, msg); - annotate_doc_comment(&mut err, sess.source_map(), sp); + annotate_doc_comment(sess.dcx(), &mut err, sess.source_map(), sp); err.emit(); return dummy_syn_ext(); } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 0311aa94cd485..f4ac010691cd4 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -261,7 +261,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let semi = expr.span.shrink_to_hi().with_hi(semi_span.hi()); let sugg = crate::errors::RemoveSemiForCoerce { expr: expr.span, ret, semi }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } /// When the previously checked expression (the scrutinee) diverges, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index f21de1609cb7f..2142bb914209a 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -993,19 +993,25 @@ impl<'a, 'tcx> CastCheck<'tcx> { if let Some((deref_ty, _)) = derefed { // Give a note about what the expr derefs to. if deref_ty != self.expr_ty.peel_refs() { - err.subdiagnostic(errors::DerefImplsIsEmpty { - span: self.expr_span, - deref_ty: fcx.ty_to_string(deref_ty), - }); + err.subdiagnostic( + fcx.dcx(), + errors::DerefImplsIsEmpty { + span: self.expr_span, + deref_ty: fcx.ty_to_string(deref_ty), + }, + ); } // Create a multipart suggestion: add `!` and `.is_empty()` in // place of the cast. - err.subdiagnostic(errors::UseIsEmpty { - 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), - }); + err.subdiagnostic( + fcx.dcx(), + errors::UseIsEmpty { + lo: self.expr_span.shrink_to_lo(), + hi: self.span.with_lo(self.expr_span.hi()), + expr_ty: fcx.ty_to_string(self.expr_ty), + }, + ); } } } diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 19bdeab409bb7..7f30b36a1f94a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -395,7 +395,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(sp) = tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } oprnd_t = Ty::new_error(tcx, err.emit()); } @@ -2050,7 +2050,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .shrink_to_hi() .to(range_end.span); - err.subdiagnostic(TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr }); + err.subdiagnostic( + self.dcx(), + TypeMismatchFruTypo { expr_span: range_start.span, fru_span, expr }, + ); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 65b8505c09098..339bc9f0f7a99 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1269,7 +1269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // The user provided `ptr::null()`, but the function expects // `ptr::null_mut()`. - err.subdiagnostic(SuggestPtrNullMut { span: arg.span }); + err.subdiagnostic(self.dcx(), SuggestPtrNullMut { span: arg.span }); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 8b6f263b1a746..c1a32a1afa3cf 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -458,13 +458,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // but those checks need to be a bit more delicate and the benefit is diminishing. if self.can_eq(self.param_env, found_ty_inner, peeled) && error_tys_equate_as_ref { let sugg = prefix_wrap(".as_ref()"); - err.subdiagnostic(errors::SuggestConvertViaMethod { - span: expr.span.shrink_to_hi(), - sugg, - expected, - found, - borrow_removal_span, - }); + err.subdiagnostic( + self.dcx(), + errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }, + ); return true; } else if let Some((deref_ty, _)) = self.autoderef(expr.span, found_ty_inner).silence_errors().nth(1) @@ -472,13 +475,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && error_tys_equate_as_ref { let sugg = prefix_wrap(".as_deref()"); - err.subdiagnostic(errors::SuggestConvertViaMethod { - span: expr.span.shrink_to_hi(), - sugg, - expected, - found, - borrow_removal_span, - }); + err.subdiagnostic( + self.dcx(), + errors::SuggestConvertViaMethod { + span: expr.span.shrink_to_hi(), + sugg, + expected, + found, + borrow_removal_span, + }, + ); return true; } else if let ty::Adt(adt, _) = found_ty_inner.peel_refs().kind() && Some(adt.did()) == self.tcx.lang_items().string() @@ -565,7 +571,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { end: span.shrink_to_hi(), }, }; - err.subdiagnostic(suggest_boxing); + err.subdiagnostic(self.dcx(), suggest_boxing); true } else { @@ -799,29 +805,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match &fn_decl.output { &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() && !can_suggest => { // `fn main()` must return `()`, do not suggest changing return type - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Unit { span }); + err.subdiagnostic(self.dcx(), errors::ExpectedReturnTypeLabel::Unit { span }); return true; } &hir::FnRetTy::DefaultReturn(span) if expected.is_unit() => { if let Some(found) = found.make_suggestable(self.tcx, false) { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span, - found: found.to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { span, found: found.to_string() }, + ); return true; } else if let ty::Closure(_, args) = found.kind() // FIXME(compiler-errors): Get better at printing binders... && let closure = args.as_closure() && closure.sig().is_suggestable(self.tcx, false) { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span, - found: closure.print_as_impl_trait().to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { + span, + found: closure.print_as_impl_trait().to_string(), + }, + ); return true; } else { // FIXME: if `found` could be `impl Iterator` we should suggest that. - err.subdiagnostic(errors::AddReturnTypeSuggestion::MissingHere { span }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::MissingHere { span }, + ); return true; } } @@ -843,16 +855,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!(?found); if found.is_suggestable(self.tcx, false) { if term.span.is_empty() { - err.subdiagnostic(errors::AddReturnTypeSuggestion::Add { - span: term.span, - found: found.to_string(), - }); + err.subdiagnostic( + self.dcx(), + errors::AddReturnTypeSuggestion::Add { + span: term.span, + found: found.to_string(), + }, + ); return true; } else { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { - span: term.span, - expected, - }); + err.subdiagnostic( + self.dcx(), + errors::ExpectedReturnTypeLabel::Other { + span: term.span, + expected, + }, + ); } } } else { @@ -867,10 +885,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.normalize(hir_ty.span, ty); let ty = self.tcx.instantiate_bound_regions_with_erased(ty); if self.can_coerce(expected, ty) { - err.subdiagnostic(errors::ExpectedReturnTypeLabel::Other { - span: hir_ty.span, - expected, - }); + err.subdiagnostic( + self.dcx(), + errors::ExpectedReturnTypeLabel::Other { span: hir_ty.span, expected }, + ); self.try_suggest_return_impl_trait(err, expected, ty, fn_id); return true; } @@ -1106,7 +1124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); if let Some(sp) = self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp) { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); true } else { false @@ -1220,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { return false; }; - diag.subdiagnostic(subdiag); + diag.subdiagnostic(self.dcx(), subdiag); return true; } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 729ce1f00cd8b..2269e9f7d4c3d 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3173,19 +3173,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if impls_trait(trait_info.def_id) { self.suggest_valid_traits(err, vec![trait_info.def_id], false); } else { - err.subdiagnostic(CandidateTraitNote { - span: self.tcx.def_span(trait_info.def_id), - trait_name: self.tcx.def_path_str(trait_info.def_id), - item_name, - action_or_ty: if trait_missing_method { - "NONE".to_string() - } else { - param_type.map_or_else( - || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented. - ToString::to_string, - ) + err.subdiagnostic( + self.dcx(), + CandidateTraitNote { + span: self.tcx.def_span(trait_info.def_id), + trait_name: self.tcx.def_path_str(trait_info.def_id), + item_name, + action_or_ty: if trait_missing_method { + "NONE".to_string() + } else { + 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 => { diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 9a8444e6a2bcd..929b3557f5242 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -824,7 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the previous expression was a block expression, suggest parentheses // (turning this into a binary subtraction operation instead.) // for example, `{2} - 2` -> `({2}) - 2` (see src\test\ui\parser\expr-as-stmt.rs) - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } else { match actual.kind() { Uint(_) if op == hir::UnOp::Neg => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index b953b25d6c4cf..280701b8ec6d5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -846,7 +846,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { arm_ty, arm_span, ) { - err.subdiagnostic(subdiag); + err.subdiagnostic(self.dcx(), subdiag); } if let hir::Node::Expr(m) = self.tcx.parent_hir_node(scrut_hir_id) && let hir::Node::Stmt(stmt) = self.tcx.parent_hir_node(m.hir_id) @@ -892,7 +892,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { else_ty, else_span, ) { - err.subdiagnostic(subdiag); + err.subdiagnostic(self.dcx(), subdiag); } // don't suggest wrapping either blocks in `if .. {} else {}` let is_empty_arm = |id| { diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 02200d6a4aaf5..50ac6235debc0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -342,7 +342,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { trait_predicates: trait_predicates.join(", "), } }; - err.subdiagnostic(suggestion); + err.subdiagnostic(self.dcx(), suggestion); } pub(super) fn report_placeholder_failure( diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 248e1c0fcc878..31e980fdfabe3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -84,7 +84,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { start_sp: return_sp.with_hi(return_sp.lo() + BytePos(4)), end_sp: return_sp.shrink_to_hi(), }; - err.subdiagnostic(sugg); + err.subdiagnostic(self.dcx(), sugg); let mut starts = Vec::new(); let mut ends = Vec::new(); @@ -93,7 +93,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ends.push(span.shrink_to_hi()); } let sugg = SuggestBoxingForReturnImplTrait::BoxReturnExpr { starts, ends }; - err.subdiagnostic(sugg); + err.subdiagnostic(self.dcx(), sugg); } pub(super) fn suggest_tuple_pattern( @@ -138,7 +138,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { span_low: cause.span.shrink_to_lo(), span_high: cause.span.shrink_to_hi(), }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } _ => { // More than one matching variant. @@ -147,7 +147,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { cause_span: cause.span, compatible_variants, }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } } } @@ -219,9 +219,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { }, (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => { // FIXME: Seems like we can't have a suggestion and a note with different spans in a single subdiagnostic - diag.subdiagnostic(ConsiderAddingAwait::FutureSugg { - span: exp_span.shrink_to_hi(), - }); + diag.subdiagnostic( + self.dcx(), + ConsiderAddingAwait::FutureSugg { span: exp_span.shrink_to_hi() }, + ); Some(ConsiderAddingAwait::FutureSuggNote { span: exp_span }) } (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code() @@ -246,7 +247,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { _ => None, }; if let Some(subdiag) = subdiag { - diag.subdiagnostic(subdiag); + diag.subdiagnostic(self.dcx(), subdiag); } } @@ -282,7 +283,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } else { return; }; - diag.subdiagnostic(suggestion); + diag.subdiagnostic(self.dcx(), suggestion); } } } @@ -322,15 +323,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (true, false) => FunctionPointerSuggestion::UseRef { span, fn_name }, (false, true) => FunctionPointerSuggestion::RemoveRef { span, fn_name }, (true, true) => { - diag.subdiagnostic(FnItemsAreDistinct); + diag.subdiagnostic(self.dcx(), FnItemsAreDistinct); FunctionPointerSuggestion::CastRef { span, fn_name, sig: *sig } } (false, false) => { - diag.subdiagnostic(FnItemsAreDistinct); + diag.subdiagnostic(self.dcx(), FnItemsAreDistinct); FunctionPointerSuggestion::Cast { span, fn_name, sig: *sig } } }; - diag.subdiagnostic(sugg); + diag.subdiagnostic(self.dcx(), sugg); } (ty::FnDef(did1, args1), ty::FnDef(did2, args2)) => { let expected_sig = @@ -339,7 +340,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &(self.normalize_fn_sig)(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2)); if self.same_type_modulo_infer(*expected_sig, *found_sig) { - diag.subdiagnostic(FnUniqTypes); + diag.subdiagnostic(self.dcx(), FnUniqTypes); } if !self.same_type_modulo_infer(*found_sig, *expected_sig) @@ -368,7 +369,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } }; - diag.subdiagnostic(sug); + diag.subdiagnostic(self.dcx(), sug); } (ty::FnDef(did, args), ty::FnPtr(sig)) => { let expected_sig = @@ -387,7 +388,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { format!("{fn_name} as {found_sig}") }; - diag.subdiagnostic(FnConsiderCasting { casting }); + diag.subdiagnostic(self.dcx(), FnConsiderCasting { casting }); } _ => { return; @@ -819,7 +820,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let diag = self.consider_returning_binding_diag(blk, expected_ty); match diag { Some(diag) => { - err.subdiagnostic(diag); + err.subdiagnostic(self.dcx(), diag); true } None => false, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 7445e2e80b407..2987d8a5ed0b2 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1758,7 +1758,7 @@ impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> { diag.note(note.to_string()); } if let Some(sugg) = self.suggestion { - diag.subdiagnostic(sugg); + diag.subdiagnostic(diag.dcx, sugg); } } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index 85bb9584a0575..ae481efb263df 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -331,44 +331,7 @@ impl DiagnosticDeriveVariantBuilder { } } (Meta::Path(_), "subdiagnostic") => { - if FieldInnerTy::from_type(&info.binding.ast().ty).will_iterate() { - let DiagnosticDeriveKind::Diagnostic = self.kind else { - // No eager translation for lints. - return Ok(quote! { diag.subdiagnostic(#binding); }); - }; - return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); - } else { - return Ok(quote! { diag.subdiagnostic(#binding); }); - } - } - (Meta::List(meta_list), "subdiagnostic") => { - let err = || { - span_err( - meta_list.span().unwrap(), - "`eager` is the only supported nested attribute for `subdiagnostic`", - ) - .emit(); - }; - - let Ok(p): Result = meta_list.parse_args() else { - err(); - return Ok(quote! {}); - }; - - if !p.is_ident("eager") { - err(); - return Ok(quote! {}); - } - - match &self.kind { - DiagnosticDeriveKind::Diagnostic => {} - DiagnosticDeriveKind::LintDiagnostic => { - throw_invalid_attr!(attr, |diag| { - diag.help("eager subdiagnostics are not supported on lints") - }) - } - }; - return Ok(quote! { diag.eager_subdiagnostic(dcx, #binding); }); + return Ok(quote! { diag.subdiagnostic(diag.dcx, #binding); }); } _ => (), } diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 692f4511bb807..a0235f20a0570 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1109,7 +1109,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( let all_arms_have_guards = arms.iter().all(|arm_id| thir[*arm_id].guard.is_some()); if !is_empty_match && all_arms_have_guards { - err.subdiagnostic(NonExhaustiveMatchAllArmsGuarded); + err.subdiagnostic(cx.tcx.dcx(), NonExhaustiveMatchAllArmsGuarded); } if let Some((span, sugg)) = suggestion { err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders); diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 30de40e226c33..ff4918df9a262 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -270,7 +270,7 @@ impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> { fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::DiagnosticBuilder<'a, ()>) { diag.span_label(self.yield_sp, fluent::_subdiag::label); if let Some(reason) = self.reason { - diag.subdiagnostic(reason); + diag.subdiagnostic(diag.dcx, reason); } diag.span_help(self.src_sp, fluent::_subdiag::help); diag.arg("pre", self.pre); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 445d5b2ce790c..e44c63f1ed760 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2350,7 +2350,7 @@ impl<'a> Parser<'a> { let mut err = self.dcx().struct_span_err(span, msg); let sp = self.sess.source_map().start_point(self.token.span); if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1a57474bac289..06134818435ca 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1433,7 +1433,7 @@ impl<'a> Parser<'a> { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. if let Some(sp) = this.sess.ambiguous_block_expr_parse.borrow().get(&lo) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(this.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } err }) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 8050b34956ce9..a34adbe7f674d 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1917,7 +1917,7 @@ impl<'a> Parser<'a> { if self.token.kind == token::Not { if let Err(mut err) = self.unexpected::() { // Encounter the macro invocation - err.subdiagnostic(MacroExpandsToAdtField { adt_ty }); + err.subdiagnostic(self.dcx(), MacroExpandsToAdtField { adt_ty }); return Err(err); } } @@ -2336,10 +2336,13 @@ impl<'a> Parser<'a> { .into_iter() .any(|s| self.prev_token.is_ident_named(s)); - err.subdiagnostic(errors::FnTraitMissingParen { - span: self.prev_token.span, - machine_applicable, - }); + err.subdiagnostic( + self.dcx(), + errors::FnTraitMissingParen { + span: self.prev_token.span, + machine_applicable, + }, + ); } return Err(err); } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 12260ec95a5b9..75fc013d3e6fe 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -843,7 +843,7 @@ impl<'a> Parser<'a> { let sp = self.sess.source_map().start_point(self.token.span); if let Some(sp) = self.sess.ambiguous_block_expr_parse.borrow().get(&sp) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(self.dcx(), ExprParenthesesNeeded::surrounding(*sp)); } Err(err) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d91a865e38aba..737481c78db68 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -403,9 +403,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(suggestion) = suggestion { - err.subdiagnostic(ChangeImportBindingSuggestion { span: binding_span, suggestion }); + err.subdiagnostic( + self.dcx(), + ChangeImportBindingSuggestion { span: binding_span, suggestion }, + ); } else { - err.subdiagnostic(ChangeImportBinding { span: binding_span }); + err.subdiagnostic(self.dcx(), ChangeImportBinding { span: binding_span }); } } @@ -1430,17 +1433,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules { - err.subdiagnostic(MaybeMissingMacroRulesName { span: ident.span }); + err.subdiagnostic(self.dcx(), MaybeMissingMacroRulesName { span: ident.span }); return; } if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) { - err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident }); + err.subdiagnostic(self.dcx(), ExplicitUnsafeTraits { span: ident.span, ident }); return; } if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { - err.subdiagnostic(AddedMacroUse); + err.subdiagnostic(self.dcx(), AddedMacroUse); return; } @@ -1450,10 +1453,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let span = self.def_span(def_id); let source_map = self.tcx.sess.source_map(); let head_span = source_map.guess_head_span(span); - err.subdiagnostic(ConsiderAddingADerive { - span: head_span.shrink_to_lo(), - suggestion: "#[derive(Default)]\n".to_string(), - }); + err.subdiagnostic( + self.dcx(), + ConsiderAddingADerive { + span: head_span.shrink_to_lo(), + suggestion: "#[derive(Default)]\n".to_string(), + }, + ); } for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] { if let Ok(binding) = self.early_resolve_ident_in_lexical_scope( diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 30fb35238c3c7..dcd01b9b33417 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1262,12 +1262,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // exclude decl_macro if self.get_macro_by_def_id(def_id).macro_rules => { - err.subdiagnostic(ConsiderAddingMacroExport { + err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport { span: binding.span, }); } _ => { - err.subdiagnostic(ConsiderMarkingAsPub { + err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub { span: import.span, ident, }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 5d712461993d8..7f0d8374b3abc 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1095,11 +1095,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { Side::Start => (segment.ident.span.between(range.span), " @ ".into()), Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)), }; - err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { - span, - ident: segment.ident, - snippet, - }); + err.subdiagnostic( + self.r.dcx(), + errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg { + span, + ident: segment.ident, + snippet, + }, + ); } enum Side { @@ -1191,10 +1194,13 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { }); if let Some(param) = param { - err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg { - span: param.shrink_to_lo(), - applicability, - }); + err.subdiagnostic( + self.r.dcx(), + errors::UnexpectedResChangeTyToConstParamSugg { + span: param.shrink_to_lo(), + applicability, + }, + ); } } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 8adb0cbcc9d76..a906d5532b5a0 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -173,21 +173,21 @@ pub fn add_feature_diagnostics_for_issue( feature_from_cli: bool, ) { if let Some(n) = find_feature_issue(feature, issue) { - err.subdiagnostic(FeatureDiagnosticForIssue { n }); + err.subdiagnostic(sess.dcx(), FeatureDiagnosticForIssue { n }); } // #23973: do not suggest `#![feature(...)]` if we are in beta/stable if sess.parse_sess.unstable_features.is_nightly_build() { if feature_from_cli { - err.subdiagnostic(CliFeatureDiagnosticHelp { feature }); + err.subdiagnostic(sess.dcx(), CliFeatureDiagnosticHelp { feature }); } else { - err.subdiagnostic(FeatureDiagnosticHelp { feature }); + err.subdiagnostic(sess.dcx(), FeatureDiagnosticHelp { feature }); } if sess.opts.unstable_opts.ui_testing { - err.subdiagnostic(SuggestUpgradeCompiler::ui_testing()); + err.subdiagnostic(sess.dcx(), SuggestUpgradeCompiler::ui_testing()); } else if let Some(suggestion) = SuggestUpgradeCompiler::new() { - err.subdiagnostic(suggestion); + err.subdiagnostic(sess.dcx(), suggestion); } } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index c7b56aac7e55b..a8b6fc1f12c26 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -4830,11 +4830,14 @@ fn hint_missing_borrow<'tcx>( } if !to_borrow.is_empty() { - err.subdiagnostic(errors::AdjustSignatureBorrow::Borrow { to_borrow }); + err.subdiagnostic(infcx.dcx(), errors::AdjustSignatureBorrow::Borrow { to_borrow }); } if !remove_borrow.is_empty() { - err.subdiagnostic(errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow }); + err.subdiagnostic( + infcx.dcx(), + errors::AdjustSignatureBorrow::RemoveBorrow { remove_borrow }, + ); } } diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 7f91af59d5622..ed401d5751b69 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -504,7 +504,7 @@ pub fn report_msg<'tcx>( let is_local = machine.is_local(frame_info); // No span for non-local frames and the first frame (which is the error site). if is_local && idx > 0 { - err.eager_subdiagnostic(err.dcx, frame_info.as_note(machine.tcx)); + err.subdiagnostic(err.dcx, frame_info.as_note(machine.tcx)); } else { let sm = sess.source_map(); let span = sm.span_to_embeddable_string(frame_info.span); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index f0af401d3da4b..cff025cf2ab3a 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; @@ -40,6 +41,16 @@ impl Translate for SilentEmitter { fn fallback_fluent_bundle(&self) -> &rustc_errors::FluentBundle { panic!("silent emitter attempted to translate a diagnostic"); } + + // Override `translate_message` for the silent emitter because eager translation of + // subdiagnostics result in a call to this. + fn translate_message<'a>( + &'a self, + message: &'a rustc_errors::DiagnosticMessage, + _: &'a rustc_errors::translation::FluentArgs<'_>, + ) -> Result, rustc_errors::error::TranslateError<'_>> { + rustc_errors::emitter::silent_translate(message) + } } impl Emitter for SilentEmitter { diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index d3cfd28082d61..6cc6fdfc0eb2b 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -701,7 +701,7 @@ struct RawIdentDiagnosticArg { #[diag(no_crate_example)] struct SubdiagnosticBad { #[subdiagnostic(bad)] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -717,7 +717,7 @@ struct SubdiagnosticBadStr { #[diag(no_crate_example)] struct SubdiagnosticBadTwice { #[subdiagnostic(bad, bad)] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -725,7 +725,7 @@ struct SubdiagnosticBadTwice { #[diag(no_crate_example)] struct SubdiagnosticBadLitStr { #[subdiagnostic("bad")] - //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic` + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -739,8 +739,9 @@ struct SubdiagnosticEagerLint { #[derive(Diagnostic)] #[diag(no_crate_example)] -struct SubdiagnosticEagerCorrect { +struct SubdiagnosticEagerFormerlyCorrect { #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute note: Note, } @@ -761,6 +762,7 @@ pub(crate) struct SubdiagnosticWithSuggestion { #[diag(no_crate_example)] struct SubdiagnosticEagerSuggestion { #[subdiagnostic(eager)] + //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute sub: SubdiagnosticWithSuggestion, } diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 2032b8a972a3b..f2dbc718c7627 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -468,11 +468,11 @@ LL | #[label] | = help: `#[label]` and `#[suggestion]` can only be applied to fields -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:703:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:703:5 | LL | #[subdiagnostic(bad)] - | ^^^^^^^^^^^^^ + | ^ error: `#[subdiagnostic = ...]` is not a valid attribute --> $DIR/diagnostic-derive.rs:711:5 @@ -480,40 +480,50 @@ error: `#[subdiagnostic = ...]` is not a valid attribute LL | #[subdiagnostic = "bad"] | ^ -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:719:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:719:5 | LL | #[subdiagnostic(bad, bad)] - | ^^^^^^^^^^^^^ + | ^ -error: `eager` is the only supported nested attribute for `subdiagnostic` - --> $DIR/diagnostic-derive.rs:727:7 +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:727:5 | LL | #[subdiagnostic("bad")] - | ^^^^^^^^^^^^^ + | ^ error: `#[subdiagnostic(...)]` is not a valid attribute --> $DIR/diagnostic-derive.rs:735:5 | LL | #[subdiagnostic(eager)] | ^ + +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:743:5 | - = help: eager subdiagnostics are not supported on lints +LL | #[subdiagnostic(eager)] + | ^ + +error: `#[subdiagnostic(...)]` is not a valid attribute + --> $DIR/diagnostic-derive.rs:764:5 + | +LL | #[subdiagnostic(eager)] + | ^ error: expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive.rs:793:23 + --> $DIR/diagnostic-derive.rs:795:23 | LL | #[suggestion(code())] | ^ error: `code(...)` must contain only string literals - --> $DIR/diagnostic-derive.rs:801:23 + --> $DIR/diagnostic-derive.rs:803:23 | LL | #[suggestion(code(foo))] | ^^^ error: `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive.rs:825:5 + --> $DIR/diagnostic-derive.rs:827:5 | LL | #[suggestion(no_crate_suggestion, code = "")] | ^ @@ -529,13 +539,13 @@ LL | #[diag = "E0123"] | ^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:801:23 + --> $DIR/diagnostic-derive.rs:803:23 | LL | #[suggestion(code(foo))] | ^^^ maybe a missing crate `core`? error[E0433]: failed to resolve: maybe a missing crate `core`? - --> $DIR/diagnostic-derive.rs:810:25 + --> $DIR/diagnostic-derive.rs:812:25 | LL | #[suggestion(code = 3)] | ^ maybe a missing crate `core`? @@ -601,7 +611,7 @@ LL | #[diag(nonsense, code = E0123)] | ^^^^^^^^ not found in `crate::fluent_generated` error[E0425]: cannot find value `__code_34` in this scope - --> $DIR/diagnostic-derive.rs:807:10 + --> $DIR/diagnostic-derive.rs:809:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ not found in this scope @@ -622,7 +632,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC = note: this error originates in the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 84 previous errors +error: aborting due to 86 previous errors Some errors have detailed explanations: E0277, E0425, E0433. For more information about an error, try `rustc --explain E0277`. From 17066870cd5c5ad367a0232501f6c8d71b4ddea5 Mon Sep 17 00:00:00 2001 From: Johannes Lade Date: Thu, 15 Feb 2024 17:33:37 +0100 Subject: [PATCH 03/10] Fix typo in VecDeque::handle_capacity_increase() doc comment. Strategies B and C both show a full buffer before the capacity increase, while strategy A had one empty element left. Filled the last element in. --- library/alloc/src/collections/vec_deque/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index d062587b8f533..bcba6525fda15 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -485,10 +485,10 @@ impl VecDeque { // H := head // L := last element (`self.to_physical_idx(self.len - 1)`) // - // H L - // [o o o o o o o . ] - // H L - // A [o o o o o o o . . . . . . . . . ] + // H L + // [o o o o o o o o ] + // H L + // A [o o o o o o o o . . . . . . . . ] // L H // [o o o o o o o o ] // H L From 7c2db703b0b56cede3d8ce264e9d1fcdb1397f94 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 11 Feb 2024 17:18:57 -0500 Subject: [PATCH 04/10] Don't use mem::zeroed in vec::IntoIter --- library/alloc/src/vec/into_iter.rs | 63 ++++++++++++++---------------- tests/codegen/vec-iter.rs | 17 +++++++- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index 63d8fe19ac35c..dfd42ca06193a 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -11,7 +11,7 @@ use core::iter::{ TrustedRandomAccessNoCoerce, }; use core::marker::PhantomData; -use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties}; +use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties}; use core::num::NonZero; #[cfg(not(no_global_oom_handling))] use core::ops::Deref; @@ -200,27 +200,23 @@ impl Iterator for IntoIter { #[inline] fn next(&mut self) -> Option { - if T::IS_ZST { - if self.ptr.as_ptr() == self.end as *mut _ { - 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() }) + let ptr = if T::IS_ZST { + if self.ptr.as_ptr() == self.end as *mut T { + return None; } + // `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 { if self.ptr == non_null!(self.end, T) { - None - } else { - let old = self.ptr; - self.ptr = unsafe { old.add(1) }; - - Some(unsafe { ptr::read(old.as_ptr()) }) + return None; } - } + let old = self.ptr; + self.ptr = unsafe { old.add(1) }; + old + }; + Some(unsafe { ptr.read() }) } #[inline] @@ -305,7 +301,7 @@ impl Iterator for IntoIter { // Also note the implementation of `Self: TrustedRandomAccess` requires // that `T: Copy` so reading elements from the buffer doesn't invalidate // 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 DoubleEndedIterator for IntoIter { #[inline] fn next_back(&mut self) -> Option { if T::IS_ZST { - if self.end as *mut _ == self.ptr.as_ptr() { - 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() }) + if self.ptr.as_ptr() == self.end as *mut _ { + return None; } + // 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 { - if non_null!(self.end, T) == self.ptr { - None - } else { - let new_end = unsafe { non_null!(self.end, T).sub(1) }; - *non_null!(mut self.end, T) = new_end; - - Some(unsafe { ptr::read(new_end.as_ptr()) }) + if self.ptr == non_null!(self.end, T) { + return None; + } + unsafe { + self.end = self.end.sub(1); + Some(ptr::read(self.end)) } } } diff --git a/tests/codegen/vec-iter.rs b/tests/codegen/vec-iter.rs index 0282791e9d169..4e2068587510c 100644 --- a/tests/codegen/vec-iter.rs +++ b/tests/codegen/vec-iter.rs @@ -32,9 +32,9 @@ pub fn vec_iter_is_empty_nonnull(it: &vec::IntoIter) -> bool { it.is_empty() } -// CHECK-LABEL: @vec_iter_next +// CHECK-LABEL: @vec_iter_next_nonnull #[no_mangle] -pub fn vec_iter_next(it: &mut vec::IntoIter) -> Option { +pub fn vec_iter_next_nonnull(it: &mut vec::IntoIter) -> Option { // CHECK: load ptr // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -44,3 +44,16 @@ pub fn vec_iter_next(it: &mut vec::IntoIter) -> Option { // CHECK: ret it.next() } + +// CHECK-LABEL: @vec_iter_next_back_nonnull +#[no_mangle] +pub fn vec_iter_next_back_nonnull(it: &mut vec::IntoIter) -> Option { + // CHECK: load ptr + // CHECK-SAME: !nonnull + // CHECK-SAME: !noundef + // CHECK: load ptr + // CHECK-SAME: !nonnull + // CHECK-SAME: !noundef + // CHECK: ret + it.next_back() +} From ede99234c48c120b909990ee2ee51dd87cfed6f5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 17 Feb 2024 10:51:35 +1100 Subject: [PATCH 05/10] Make `CodegenBackend::join_codegen` infallible. Because they all are, in practice. --- compiler/rustc_codegen_cranelift/src/lib.rs | 6 +++--- compiler/rustc_codegen_gcc/src/lib.rs | 8 +++----- compiler/rustc_codegen_llvm/src/lib.rs | 4 ++-- compiler/rustc_codegen_ssa/src/traits/backend.rs | 2 +- compiler/rustc_interface/src/queries.rs | 2 +- .../hotplug_codegen_backend/the_backend.rs | 4 ++-- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 7c432e9c59051..7e2e1f7c6ac07 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -233,11 +233,11 @@ impl CodegenBackend for CraneliftCodegenBackend { ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - Ok(ongoing_codegen + ) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::() .unwrap() - .join(sess, self.config.borrow().as_ref().unwrap())) + .join(sess, self.config.borrow().as_ref().unwrap()) } fn link( diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 863b6333bcc29..09ce059476ec7 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -217,13 +217,11 @@ impl CodegenBackend for GccCodegenBackend { Box::new(res) } - fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { - let (codegen_results, work_products) = ongoing_codegen + fn join_codegen(&self, ongoing_codegen: Box, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap) { + ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") - .join(sess); - - Ok((codegen_results, work_products)) + .join(sess) } fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> { diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index e688e84db61a5..35210b0b2e86d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -369,7 +369,7 @@ impl CodegenBackend for LlvmCodegenBackend { ongoing_codegen: Box, sess: &Session, outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { + ) -> (CodegenResults, FxIndexMap) { let (codegen_results, work_products) = ongoing_codegen .downcast::>() .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") @@ -382,7 +382,7 @@ impl CodegenBackend for LlvmCodegenBackend { }); } - Ok((codegen_results, work_products)) + (codegen_results, work_products) } fn link( diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 8e9907ed8bb03..cb1feff13363e 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -102,7 +102,7 @@ pub trait CodegenBackend { ongoing_codegen: Box, sess: &Session, outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed>; + ) -> (CodegenResults, FxIndexMap); /// This is called on the returned `CodegenResults` from `join_codegen` fn link( diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2a4eefb7f771b..211bcb9da94db 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -259,7 +259,7 @@ pub struct Linker { impl Linker { pub fn link(self, sess: &Session, codegen_backend: &dyn CodegenBackend) -> Result<()> { 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()?; diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 9e0a7ba63d05f..28a1e27cccccd 100644 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -49,11 +49,11 @@ impl CodegenBackend for TheBackend { ongoing_codegen: Box, _sess: &Session, _outputs: &OutputFilenames, - ) -> Result<(CodegenResults, FxIndexMap), ErrorGuaranteed> { + ) -> (CodegenResults, FxIndexMap) { let codegen_results = ongoing_codegen .downcast::() .expect("in join_codegen: ongoing_codegen is not a CodegenResults"); - Ok((*codegen_results, FxIndexMap::default())) + (*codegen_results, FxIndexMap::default()) } fn link( From 228441dbd6e9fc823da545ed29499f6f8e5d7101 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 16 Feb 2024 17:56:15 +0000 Subject: [PATCH 06/10] Use fulfillment in next trait solver coherence --- .../src/solve/inspect/analyse.rs | 8 ++- .../src/traits/coherence.rs | 70 ++++++++++--------- tests/ui/coherence/coherent-due-to-fulfill.rs | 20 ++++++ .../incoherent-even-though-we-fulfill.rs | 22 ++++++ .../incoherent-even-though-we-fulfill.stderr | 14 ++++ 5 files changed, 97 insertions(+), 37 deletions(-) create mode 100644 tests/ui/coherence/coherent-due-to-fulfill.rs create mode 100644 tests/ui/coherence/incoherent-even-though-we-fulfill.rs create mode 100644 tests/ui/coherence/incoherent-even-though-we-fulfill.stderr diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index f33d0f397ce9e..9020c11b2559e 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -230,8 +230,10 @@ impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { goal: Goal<'tcx, ty::Predicate<'tcx>>, visitor: &mut V, ) -> ControlFlow { - let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); - let proof_tree = proof_tree.unwrap(); - visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + self.probe(|_| { + let (_, proof_tree) = self.evaluate_root_goal(goal, GenerateProofTree::Yes); + let proof_tree = proof_tree.unwrap(); + visitor.visit_goal(&InspectGoal::new(self, 0, &proof_tree)) + }) } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index e48bd437f59c5..f663f02f87289 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -8,23 +8,21 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; use crate::regions::InferCtxtRegionExt; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; -use crate::solve::{deeply_normalize_for_diagnostics, inspect}; -use crate::traits::engine::TraitEngineExt; -use crate::traits::query::evaluate_obligation::InferCtxtExt; +use crate::solve::{deeply_normalize_for_diagnostics, inspect, FulfillmentCtxt}; +use crate::traits::engine::TraitEngineExt as _; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::structural_normalize::StructurallyNormalizeExt; use crate::traits::NormalizeExt; use crate::traits::SkipLeakCheck; use crate::traits::{ - Obligation, ObligationCause, ObligationCtxt, PredicateObligation, PredicateObligations, - SelectionContext, + Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; 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::solve::{CandidateSource, Certainty, Goal}; 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>( selcx: &mut SelectionContext<'cx, 'tcx>, obligations: &'a [PredicateObligation<'tcx>], -) -> Option<&'a PredicateObligation<'tcx>> { +) -> Option> { let infcx = selcx.infcx; - obligations.iter().find(|obligation| { - let evaluation_result = if infcx.next_trait_solver() { - infcx.evaluate_obligation(obligation) - } else { + if infcx.next_trait_solver() { + let mut fulfill_cx = FulfillmentCtxt::new(infcx); + fulfill_cx.register_predicate_obligations(infcx, obligations.iter().cloned()); + + // 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 // ambiguity clauses. We cannot use this in the new solver. - selcx.evaluate_root_obligation(obligation) - }; - - match evaluation_result { - Ok(result) => !result.may_apply(), - // 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 - // success. This isn't much of a problem in the old solver, since we treat overflow - // fatally (this still can be encountered: ), - // but in the new solver, this is very important for correctness, since overflow - // *must* be treated as ambiguity for completeness. - Err(_overflow) => false, - } - }) + let evaluation_result = selcx.evaluate_root_obligation(obligation); + + match evaluation_result { + Ok(result) => !result.may_apply(), + // 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 + // success. This isn't much of a problem in the old solver, since we treat overflow + // fatally (this still can be encountered: ), + // but in the new solver, this is very important for correctness, since overflow + // *must* be treated as ambiguity for completeness. + Err(_overflow) => false, + } + }) + } } /// 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 // impl candidates do exist. let ref infcx = root_infcx.fork_with_intercrate(false); - let ocx = ObligationCtxt::new(infcx); - - ocx.register_obligation(Obligation::new( - infcx.tcx, - ObligationCause::dummy(), - param_env, - negative_predicate, - )); - if !ocx.select_all_or_error().is_empty() { + let mut fulfill_cx = FulfillmentCtxt::new(infcx); + + fulfill_cx.register_predicate_obligation( + infcx, + Obligation::new(infcx.tcx, ObligationCause::dummy(), param_env, negative_predicate), + ); + if !fulfill_cx.select_all_or_error(infcx).is_empty() { return false; } diff --git a/tests/ui/coherence/coherent-due-to-fulfill.rs b/tests/ui/coherence/coherent-due-to-fulfill.rs new file mode 100644 index 0000000000000..084f9be0a8c3f --- /dev/null +++ b/tests/ui/coherence/coherent-due-to-fulfill.rs @@ -0,0 +1,20 @@ +//@ compile-flags: -Znext-solver=coherence +//@ check-pass + +trait Mirror { + type Assoc; +} +impl 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 Foo for T where (): Mirror {} +impl Foo for T where T: Bar {} + +fn main() {} diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.rs b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs new file mode 100644 index 0000000000000..b3c9cf328c21c --- /dev/null +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=coherence + +trait Mirror { + type Assoc; +} +impl 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 Foo for T where (): Mirror {} +//~^ NOTE first implementation here +impl 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() {} diff --git a/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr new file mode 100644 index 0000000000000..b16465d201140 --- /dev/null +++ b/tests/ui/coherence/incoherent-even-though-we-fulfill.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `Foo` for type `()` + --> $DIR/incoherent-even-though-we-fulfill.rs:17:1 + | +LL | impl Foo for T where (): Mirror {} + | --------------------------------------------- first implementation here +LL | +LL | impl 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`. From dae22a598bc28fd03522fcba5d09150ca53cdc4f Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 17 Feb 2024 01:15:08 +0100 Subject: [PATCH 07/10] Fix `cfg(target_abi = "sim")` on i386-apple-ios i386-apple-ios is also a simulator target --- compiler/rustc_target/src/spec/base/apple/mod.rs | 15 ++++++++------- .../src/spec/targets/i386_apple_ios.rs | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index afd60b40c3be1..460e7e034f3a8 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -17,6 +17,7 @@ pub enum Arch { Arm64e, Arm64_32, I386, + I386_sim, I686, X86_64, X86_64h, @@ -34,7 +35,7 @@ impl Arch { Arm64 | Arm64_macabi | Arm64_sim => "arm64", Arm64e => "arm64e", Arm64_32 => "arm64_32", - I386 => "i386", + I386 | I386_sim => "i386", I686 => "i686", X86_64 | X86_64_sim | X86_64_macabi => "x86_64", X86_64h => "x86_64h", @@ -45,7 +46,7 @@ impl Arch { Cow::Borrowed(match self { Armv7k | Armv7s => "arm", 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", }) } @@ -56,7 +57,7 @@ impl Arch { X86_64_macabi | Arm64_macabi => "macabi", // x86_64-apple-ios is a simulator target, even though it isn't // declared that way in the target like the other ones... - Arm64_sim | X86_64_sim => "sim", + I386_sim | Arm64_sim | X86_64_sim => "sim", } } @@ -70,7 +71,7 @@ impl Arch { // Only macOS 10.12+ is supported, which means // 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 - I386 | I686 => "penryn", + I386 | I386_sim | I686 => "penryn", X86_64 | X86_64_sim => "penryn", X86_64_macabi => "penryn", // Note: `core-avx2` is slightly more advanced than `x86_64h`, see @@ -85,7 +86,7 @@ impl Arch { fn stack_probes(self) -> StackProbeType { match self { 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, } } @@ -302,8 +303,8 @@ fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow]> // Otherwise if cross-compiling for a different OS/SDK, remove any part // of the linking environment that's wrong and reversed. match arch { - Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim - | X86_64h | Arm64_sim => { + Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I386_sim | I686 | X86_64 + | X86_64_sim | X86_64h | Arm64_sim => { cvs!["MACOSX_DEPLOYMENT_TARGET"] } X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"], diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index a221538b9022f..63133ff99ea4a 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -2,7 +2,7 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { - let arch = Arch::I386; + let arch = Arch::I386_sim; Target { // Clang automatically chooses a more specific target based on // IPHONEOS_DEPLOYMENT_TARGET. From d80198595c926949a84944220a8176940a32654b Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 17 Feb 2024 01:16:11 +0100 Subject: [PATCH 08/10] Fix comment --- compiler/rustc_target/src/spec/base/apple/mod.rs | 2 -- compiler/rustc_target/src/spec/targets/i386_apple_ios.rs | 2 ++ compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs | 2 ++ compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs index 460e7e034f3a8..aee5d60626e31 100644 --- a/compiler/rustc_target/src/spec/base/apple/mod.rs +++ b/compiler/rustc_target/src/spec/base/apple/mod.rs @@ -55,8 +55,6 @@ impl Arch { match self { Armv7k | Armv7s | Arm64 | Arm64e | Arm64_32 | I386 | I686 | X86_64 | X86_64h => "", X86_64_macabi | Arm64_macabi => "macabi", - // x86_64-apple-ios is a simulator target, even though it isn't - // declared that way in the target like the other ones... I386_sim | Arm64_sim | X86_64_sim => "sim", } } diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs index 63133ff99ea4a..d78acdbd1aad5 100644 --- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{Target, TargetOptions}; pub fn target() -> Target { + // 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 { // Clang automatically chooses a more specific target based on diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs index 55165ea4ec68c..5b34390141e0e 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{ios_sim_llvm_target, opts, Arch}; use crate::spec::{SanitizerSet, Target, TargetOptions}; 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 mut base = opts("ios", arch); base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::THREAD; diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs index 20b0161255314..95033699f1af3 100644 --- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs +++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs @@ -2,6 +2,8 @@ use crate::spec::base::apple::{opts, tvos_sim_llvm_target, Arch}; use crate::spec::{Target, TargetOptions}; 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; Target { llvm_target: tvos_sim_llvm_target(arch).into(), From 3ec7d0a57c3bf82877b4a40e25a8f55cfb6e94fa Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sat, 17 Feb 2024 13:19:01 +0300 Subject: [PATCH 09/10] create stamp file for clippy in `Config::download_clippy` Due to missing stamp file, we were downloading (and applying nix patches if enabled) continuously every time `Config::download_clippy` was called. This change fixes that by creating stamp file at the end of the function. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/download.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index e63d60feff125..b4ae3578ce317 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -399,6 +399,7 @@ impl Config { self.fix_bin_or_dylib(&cargo_clippy.with_file_name(exe("clippy-driver", host))); } + self.create(&clippy_stamp, date); cargo_clippy } From 87b6f415f254345763919dcc460839be2fe9677d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 17 Feb 2024 12:46:18 +0100 Subject: [PATCH 10/10] remove a couple of redundant clones --- compiler/rustc_hir_typeck/src/_match.rs | 2 +- compiler/rustc_parse/src/parser/diagnostics.rs | 4 ++-- compiler/rustc_parse_format/src/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/diagnostics.rs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index b0caf45b40afe..7c0de1261ef08 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -311,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error: &mut bool, ) { 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 && let Some(expr) = block.expr { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 69518287f38ec..ba5954bc3ea71 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -452,7 +452,6 @@ impl<'a> Parser<'a> { let mut expected = self .expected_tokens .iter() - .cloned() .filter(|token| { // Filter out suggestions that suggest the same token which was found and deemed incorrect. fn is_ident_eq_keyword(found: &TokenKind, expected: &TokenType) -> bool { @@ -464,7 +463,7 @@ impl<'a> Parser<'a> { 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); // If the suggestion is a keyword and the found token is an ident, // the content of which are equal to the suggestion's content, @@ -483,6 +482,7 @@ impl<'a> Parser<'a> { } false }) + .cloned() .collect::>(); expected.sort_by_cached_key(|x| x.to_string()); expected.dedup(); diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 0b65f400825ae..79aab47fbe717 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -893,7 +893,7 @@ impl<'a> Parser<'a> { ParseError { description: "expected format parameter to occur after `:`".to_owned(), note: None, - label: format!("expected `{}` to occur after `:`", alignment).to_owned(), + label: format!("expected `{}` to occur after `:`", alignment), span: pos.to(pos), secondary_label: None, suggestion: Suggestion::None, diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 56978eb2ee805..5199959c0f2b3 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -84,9 +84,9 @@ pub fn span_lint_and_help( cx.span_lint(lint, span, msg.to_string(), |diag| { let help = help.to_string(); if let Some(help_span) = help_span { - diag.span_help(help_span, help.to_string()); + diag.span_help(help_span, help); } else { - diag.help(help.to_string()); + diag.help(help); } docs_link(diag, lint); });