diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 5c645c66cd71c..eef1623af3701 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -127,6 +127,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && used_place.is_prefix_of(moved_place.as_ref()) }); + //FIXME: move to ftl let partial_str = if is_partial_move { "partial " } else { "" }; let partially_str = if is_partial_move { "partially " } else { "" }; @@ -180,13 +181,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(moved_place.as_ref(), move_out.source); let move_span = move_spans.args_or_use(); - let move_msg = if move_spans.for_closure() { " into closure" } else { "" }; + let is_move_msg = move_spans.for_closure(); - let loop_message = if location == move_out.source || move_site.traversed_back_edge { - ", in previous iteration of loop" - } else { - "" - }; + let is_loop_message = location == move_out.source || move_site.traversed_back_edge; if location == move_out.source { is_loop_move = true; @@ -203,9 +200,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span, move_spans, *moved_place, - partially_str, - loop_message, - move_msg, + is_partial_move, + is_loop_message, + is_move_msg, is_loop_move, maybe_reinitialized_locations.is_empty(), ); @@ -277,12 +274,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } if needs_note { - let span = if let Some(local) = place.as_local() { - Some(self.body.local_decls[local].source_info.span) + 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, + }); } else { - None + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note { + is_partial_move, + ty, + place: ¬e_msg, + }); }; - self.note_type_does_not_implement_copy(&mut err, ¬e_msg, ty, span, partial_str); } if let UseSpans::FnSelfUse { @@ -836,11 +842,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); - move_spans.var_span_label( - &mut err, - format!("move occurs due to use{}", move_spans.describe()), - "moved", - ); + move_spans.var_subdiag(None, &mut err, None, |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => MoveUseInGenerator { var_span }, + None => MoveUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -877,13 +885,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { + borrow_spans.var_subdiag(None, &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()); match kind { - Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, - None => BorrowUsePlaceClosure { place: desc_place, var_span }, + Some(_) => { + BorrowUsePlaceGenerator { place: desc_place, var_span, is_single_var: true } + } + None => BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: true }, } }); @@ -991,16 +1001,26 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { immutable_section_description, "mutably borrow", ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + None, &mut err, - format!( - "borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - "immutable", + Some(BorrowKind::Unique), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: true, + }, + None => BorrowUsePlaceClosure { + place: desc_place, + var_span, + is_single_var: true, + }, + } + }, ); - return err; } else { first_borrow_desc = "immutable "; @@ -1073,32 +1093,48 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; if issued_spans == borrow_spans { - borrow_spans.var_span_label( - &mut err, - format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),), - gen_borrow_kind.describe_mutability(), - ); + borrow_spans.var_subdiag(None, &mut err, Some(gen_borrow_kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUsePlaceGenerator { + place: desc_place, + var_span, + is_single_var: false, + }, + None => { + BorrowUsePlaceClosure { place: desc_place, var_span, is_single_var: false } + } + } + }); } else { - let borrow_place = &issued_borrow.borrowed_place; - let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); - issued_spans.var_span_label( + issued_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "first borrow occurs due to use of {}{}", - borrow_place_desc, - issued_spans.describe(), - ), - issued_borrow.kind.describe_mutability(), + Some(issued_borrow.kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + let borrow_place = &issued_borrow.borrowed_place; + let borrow_place_desc = self.describe_any_place(borrow_place.as_ref()); + match kind { + Some(_) => { + FirstBorrowUsePlaceGenerator { place: borrow_place_desc, var_span } + } + None => FirstBorrowUsePlaceClosure { place: borrow_place_desc, var_span }, + } + }, ); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + Some(&self.infcx.tcx.sess.parse_sess.span_diagnostic), &mut err, - format!( - "second borrow occurs due to use of {}{}", - desc_place, - borrow_spans.describe(), - ), - gen_borrow_kind.describe_mutability(), + Some(gen_borrow_kind), + |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => SecondBorrowUsePlaceGenerator { place: desc_place, var_span }, + None => SecondBorrowUsePlaceClosure { place: desc_place, var_span }, + } + }, ); } @@ -1572,9 +1608,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); explanation.add_explanation_to_diagnostic( self.infcx.tcx, @@ -1788,9 +1827,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None, ); - let within = if borrow_spans.for_generator() { " by generator" } else { "" }; - - borrow_spans.args_span_label(&mut err, format!("value captured here{}", within)); + borrow_spans.args_subdiag(&mut err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::Capture { + is_within: borrow_spans.for_generator(), + args_span, + } + }); err } @@ -2214,11 +2256,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { section, "assign", ); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.buffer_error(err); @@ -2228,11 +2273,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans.var_span_label( - &mut err, - format!("borrow occurs due to use{}", loan_spans.describe()), - loan.kind.describe_mutability(), - ); + loan_spans.var_subdiag(None, &mut err, Some(loan.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => BorrowUseInGenerator { var_span }, + None => BorrowUseInClosure { var_span }, + } + }); self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( self.infcx.tcx, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c500cbc49e4a3..83ed786d0fa91 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -1,8 +1,10 @@ +// #![deny(rustc::untranslatable_diagnostic)] +// #![deny(rustc::diagnostic_outside_of_impl)] //! Borrow checker diagnostics. use itertools::Itertools; use rustc_const_eval::util::{call_kind, CallDesugaringKind}; -use rustc_errors::{Applicability, Diagnostic}; +use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::GeneratorKind; @@ -117,13 +119,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some((span, hir_place)) = self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id) { - diag.span_note( - *span, - &format!( - "closure cannot be invoked more than once because it moves the \ - variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + crate::session_diagnostics::OnClosureNote::InvokedTwice { + place_name: &ty::place_to_string_for_capture( + self.infcx.tcx, + hir_place, + ), + span: *span, + }, ); return true; } @@ -141,13 +145,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some((span, hir_place)) = self.infcx.tcx.typeck(did).closure_kind_origins().get(hir_id) { - diag.span_note( - *span, - &format!( - "closure cannot be moved more than once as it is not `Copy` due to \ - moving the variable `{}` out of its environment", - ty::place_to_string_for_capture(self.infcx.tcx, hir_place) - ), + diag.eager_subdiagnostic( + &self.infcx.tcx.sess.parse_sess.span_diagnostic, + crate::session_diagnostics::OnClosureNote::MovedTwice { + place_name: &ty::place_to_string_for_capture(self.infcx.tcx, hir_place), + span: *span, + }, ); return true; } @@ -390,26 +393,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - /// Add a note that a type does not implement `Copy` - pub(super) fn note_type_does_not_implement_copy( - &self, - err: &mut Diagnostic, - place_desc: &str, - ty: Ty<'tcx>, - span: Option, - move_prefix: &str, - ) { - let message = format!( - "{}move occurs because {} has type `{}`, which does not implement the `Copy` trait", - move_prefix, place_desc, ty, - ); - if let Some(span) = span { - err.span_label(span, message); - } else { - err.note(&message); - } - } - pub(super) fn borrowed_content_source( &self, deref_base: PlaceRef<'tcx>, @@ -590,10 +573,14 @@ impl UseSpans<'_> { } } - // Add a span label to the arguments of the closure, if it exists. - pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into) { + /// Add a span label to the arguments of the closure, if it exists. + pub(super) fn args_subdiag( + self, + err: &mut Diagnostic, + f: impl FnOnce(Span) -> crate::session_diagnostics::CaptureArgLabel, + ) { if let UseSpans::ClosureUse { args_span, .. } = self { - err.span_label(args_span, message); + err.subdiagnostic(f(args_span)); } } @@ -628,32 +615,13 @@ impl UseSpans<'_> { } } - // Add a span label to the use of the captured variable, if it exists. - pub(super) fn var_span_label( - self, - err: &mut Diagnostic, - message: impl Into, - kind_desc: impl Into, - ) { - if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { - if capture_kind_span == path_span { - err.span_label(capture_kind_span, message); - } else { - let capture_kind_label = - format!("capture is {} because of use here", kind_desc.into()); - let path_label = message; - err.span_label(capture_kind_span, capture_kind_label); - err.span_label(path_span, path_label); - } - } - } - /// Add a subdiagnostic to the use of the captured variable, if it exists. pub(super) fn var_subdiag( self, + handler: Option<&rustc_errors::Handler>, err: &mut Diagnostic, kind: Option, - f: impl Fn(Option, Span) -> crate::session_diagnostics::CaptureVarCause, + f: impl FnOnce(Option, Span) -> crate::session_diagnostics::CaptureVarCause, ) { use crate::session_diagnostics::CaptureVarKind::*; if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { @@ -663,7 +631,7 @@ impl UseSpans<'_> { rustc_middle::mir::BorrowKind::Shared | rustc_middle::mir::BorrowKind::Shallow | rustc_middle::mir::BorrowKind::Unique => { - Immute { kind_span: capture_kind_span } + Immut { kind_span: capture_kind_span } } rustc_middle::mir::BorrowKind::Mut { .. } => { @@ -673,7 +641,11 @@ impl UseSpans<'_> { None => Move { kind_span: capture_kind_span }, }); }; - err.subdiagnostic(f(generator_kind, path_span)); + let diag = f(generator_kind, path_span); + match handler { + Some(hd) => err.eager_subdiagnostic(hd, diag), + None => err.subdiagnostic(diag), + }; } } @@ -693,20 +665,6 @@ impl UseSpans<'_> { } } - /// Describe the span associated with a use of a place. - pub(super) fn describe(&self) -> &str { - match *self { - UseSpans::ClosureUse { generator_kind, .. } => { - if generator_kind.is_some() { - " in generator" - } else { - " in closure" - } - } - _ => "", - } - } - pub(super) fn or_else(self, if_other: F) -> Self where F: FnOnce() -> Self, @@ -1026,12 +984,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { move_span: Span, move_spans: UseSpans<'tcx>, moved_place: Place<'tcx>, - partially_str: &str, - loop_message: &str, - move_msg: &str, + is_partial: bool, + is_loop_message: bool, + is_move_msg: bool, is_loop_move: bool, maybe_reinitialized_locations_is_empty: bool, ) { + use crate::session_diagnostics::CaptureReasonLabel::*; + use crate::session_diagnostics::CaptureReasonNote::*; + use crate::session_diagnostics::CaptureReasonSuggest::*; if let UseSpans::FnSelfUse { var_span, fn_call_span, fn_span, kind } = move_spans { let place_name = self .describe_place(moved_place.as_ref()) @@ -1041,37 +1002,37 @@ 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.span_label( + err.subdiagnostic(Call { fn_call_span, - &format!( - "{} {}moved due to this call{}", - place_name, partially_str, loop_message - ), - ); - err.span_note( - var_span, - "this value implements `FnOnce`, which causes it to be moved when called", - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); + err.subdiagnostic(FnOnceMoveInCall { var_span }); } CallKind::Operator { self_arg, .. } => { let self_arg = self_arg.unwrap(); - err.span_label( + err.subdiagnostic(OperatorUse { fn_call_span, - &format!( - "{} {}moved due to usage in operator{}", - place_name, partially_str, loop_message - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); if self.fn_self_span_reported.insert(fn_span) { - err.span_note( + err.subdiagnostic(LhsMoveByOperator { // Check whether the source is accessible - if self.infcx.tcx.sess.source_map().is_span_accessible(self_arg.span) { + span: if self + .infcx + .tcx + .sess + .source_map() + .is_span_accessible(self_arg.span) + { self_arg.span } else { fn_call_span }, - "calling this operator moves the left-hand side", - ); + }); } } CallKind::Normal { self_arg, desugaring, is_option_or_result } => { @@ -1095,25 +1056,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => false, }; if suggest { - err.span_suggestion_verbose( - move_span.shrink_to_lo(), - &format!( - "consider iterating over a slice of the `{}`'s content to \ - avoid moving into the `for` loop", - ty, - ), - "&", - Applicability::MaybeIncorrect, - ); + err.subdiagnostic(IterateSlice { ty, span: move_span.shrink_to_lo() }); } - err.span_label( + err.subdiagnostic(ImplicitCall { fn_call_span, - &format!( - "{} {}moved due to this implicit call to `.into_iter()`{}", - place_name, partially_str, loop_message - ), - ); + 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. @@ -1122,61 +1073,46 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { // If we are in a loop this will be suggested later. if !is_loop_move { - err.span_suggestion_verbose( - move_span.shrink_to_lo(), - &format!( - "consider creating a fresh reborrow of {} here", - self.describe_place(moved_place.as_ref()) - .map(|n| format!("`{}`", n)) - .unwrap_or_else(|| "the mutable reference".to_string()), - ), - "&mut *", - Applicability::MachineApplicable, - ); + err.subdiagnostic(FreshReborrow { + place_name: &place_name, + span: move_span.shrink_to_lo(), + }); } } } else { - err.span_label( + err.subdiagnostic(MethodCall { fn_call_span, - &format!( - "{} {}moved due to this method call{}", - place_name, partially_str, loop_message - ), - ); + place_name: &place_name, + is_partial, + is_loop_message, + }); } // Avoid pointing to the same function in multiple different // error messages. if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) { - err.span_note( - self_arg.span, - &format!("this function takes ownership of the receiver `self`, which moves {}", place_name) - ); + err.subdiagnostic(FuncTakeSelf { place_name, span: self_arg.span }); } if is_option_or_result && maybe_reinitialized_locations_is_empty { - err.span_label( - var_span, - "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents", - ); + err.subdiagnostic(BorrowContent { var_span }); } } // Other desugarings takes &self, which cannot cause a move _ => {} } } else { - if move_span != span || !loop_message.is_empty() { - err.span_label( - move_span, - format!("value {}moved{} here{}", partially_str, move_msg, loop_message), - ); + if move_span != span || is_loop_message { + err.subdiagnostic(Desc { 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 loop_message.is_empty() { - move_spans.var_span_label( - err, - format!("variable {}moved due to use{}", partially_str, move_spans.describe()), - "moved", - ); + if !is_loop_message { + move_spans.var_subdiag(None, err, None, |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + match kind { + Some(_) => PartialMoveUseInGenerator { var_span, is_partial }, + None => PartialMoveUseInClosure { 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 5a47f45677ecb..a22c045789ccb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -401,7 +401,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; if let Some(use_spans) = use_spans { self.explain_captures( - &mut err, span, span, use_spans, move_place, "", "", "", false, true, + &mut err, span, span, use_spans, move_place, false, false, false, false, true, ); } err @@ -426,13 +426,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { None => "value".to_string(), }; - self.note_type_does_not_implement_copy( - err, - &place_desc, - place_ty, - Some(span), - "", - ); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); } else { binds_to.sort(); binds_to.dedup(); @@ -454,9 +453,19 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { Some(desc) => format!("`{desc}`"), None => "value".to_string(), }; - self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), ""); + err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { + is_partial_move: false, + ty: place_ty, + place: &place_desc, + span, + }); - use_spans.args_span_label(err, format!("move out of {place_desc} occurs here")); + use_spans.args_subdiag(err, |args_span| { + crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { + place: place_desc, + args_span, + } + }); } } } @@ -509,13 +518,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } if binds_to.len() == 1 { - self.note_type_does_not_implement_copy( - err, - &format!("`{}`", self.local_names[*local].unwrap()), - bind_to.ty, - Some(binding_span), - "", - ); + 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, + }); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 7457369aa58cb..db71793b03d73 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -195,13 +195,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let borrow_spans = self.borrow_spans(span, location); let borrow_span = borrow_spans.args_or_use(); err = self.cannot_borrow_path_as_mutable_because(borrow_span, &item_msg, &reason); - borrow_spans.var_span_label( + borrow_spans.var_subdiag( + None, &mut err, - format!( - "mutable borrow occurs due to use of {} in closure", - self.describe_any_place(access_place.as_ref()), - ), - "mutable", + Some(mir::BorrowKind::Mut { allow_two_phase_borrow: false }), + |_kind, var_span| { + let place = self.describe_any_place(access_place.as_ref()); + crate::session_diagnostics::CaptureVarCause::MutableBorrowUsePlaceClosure { + place, + var_span, + } + }, ); borrow_span } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 577332c0744b8..4a28dfc88a89b 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -196,7 +196,7 @@ pub(crate) enum CaptureVarPathUseCause { #[derive(Subdiagnostic)] pub(crate) enum CaptureVarKind { #[label(borrowck_capture_immute)] - Immute { + Immut { #[primary_span] kind_span: Span, }, @@ -216,16 +216,80 @@ pub(crate) enum CaptureVarKind { pub(crate) enum CaptureVarCause { #[label(borrowck_var_borrow_by_use_place_in_generator)] BorrowUsePlaceGenerator { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, #[label(borrowck_var_borrow_by_use_place_in_closure)] BorrowUsePlaceClosure { + is_single_var: bool, place: String, #[primary_span] var_span: Span, }, + #[label(borrowck_var_borrow_by_use_in_generator)] + BorrowUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_borrow_by_use_in_closure)] + BorrowUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_generator)] + MoveUseInGenerator { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_move_by_use_in_closure)] + MoveUseInClosure { + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_generator)] + FirstBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_first_borrow_by_use_place_in_closure)] + FirstBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_generator)] + SecondBorrowUsePlaceGenerator { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_second_borrow_by_use_place_in_closure)] + SecondBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_var_mutable_borrow_by_use_place_in_closure)] + MutableBorrowUsePlaceClosure { + place: String, + #[primary_span] + var_span: Span, + }, + #[label(borrowck_partial_var_move_by_use_in_generator)] + PartialMoveUseInGenerator { + #[primary_span] + var_span: Span, + is_partial: bool, + }, + #[label(borrowck_partial_var_move_by_use_in_closure)] + PartialMoveUseInClosure { + #[primary_span] + var_span: Span, + is_partial: bool, + }, } #[derive(Diagnostic)] @@ -240,3 +304,144 @@ pub(crate) struct MoveBorrow<'a> { #[label] pub borrow_span: Span, } + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonLabel<'a> { + #[label(borrowck_moved_due_to_call)] + Call { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_usage_in_operator)] + OperatorUse { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_implicit_into_iter_call)] + ImplicitCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_moved_due_to_method_call)] + MethodCall { + #[primary_span] + fn_call_span: Span, + place_name: &'a str, + is_partial: bool, + is_loop_message: bool, + }, + #[label(borrowck_value_moved_here)] + Desc { + #[primary_span] + move_span: Span, + is_partial: bool, + is_move_msg: bool, + is_loop_message: bool, + }, + #[label(borrowck_consider_borrow_type_contents)] + BorrowContent { + #[primary_span] + var_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonNote { + #[note(borrowck_moved_a_fn_once_in_call)] + FnOnceMoveInCall { + #[primary_span] + var_span: Span, + }, + #[note(borrowck_calling_operator_moves_lhs)] + LhsMoveByOperator { + #[primary_span] + span: Span, + }, + #[note(borrowck_func_take_self_moved_place)] + FuncTakeSelf { + place_name: String, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureReasonSuggest<'a, 'tcx> { + #[suggestion( + borrowck_suggest_iterate_over_slice, + applicability = "maybe-incorrect", + code = "&", + style = "verbose" + )] + IterateSlice { + ty: Ty<'tcx>, + #[primary_span] + span: Span, + }, + #[suggestion( + borrowck_suggest_create_freash_reborrow, + applicability = "machine-applicable", + code = "&mut *", + style = "verbose" + )] + FreshReborrow { + place_name: &'a str, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum CaptureArgLabel { + #[label(borrowck_value_capture_here)] + Capture { + is_within: bool, + #[primary_span] + args_span: Span, + }, + #[label(borrowck_move_out_place_here)] + MoveOutPlace { + place: String, + #[primary_span] + args_span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OnClosureNote<'a> { + #[note(borrowck_closure_invoked_twice)] + InvokedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_closure_moved_twice)] + MovedTwice { + place_name: &'a str, + #[primary_span] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum TypeNoCopy<'a, 'tcx> { + #[label(borrowck_ty_no_impl_copy)] + Label { + is_partial_move: bool, + ty: Ty<'tcx>, + place: &'a str, + #[primary_span] + span: Span, + }, + #[note(borrowck_ty_no_impl_copy)] + Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, +} diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl index 2cd4733220e82..4921b0c35a816 100644 --- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl +++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl @@ -56,18 +56,6 @@ borrowck_returned_lifetime_short = borrowck_used_impl_require_static = the used `impl` has a `'static` requirement -borrowck_capture_kind_label = - capture is {$kind_desc} because of use here - -borrowck_var_borrow_by_use_place_in_generator = - borrow occurs due to use of {$place} in closure in generator - -borrowck_var_borrow_by_use_place_in_closure = - borrow occurs due to use of {$place} in closure - -borrowck_var_borrow_by_use_place = - borrow occurs due to use of {$place} - borrowck_borrow_due_to_use_generator = borrow occurs due to use in generator @@ -101,12 +89,63 @@ borrowck_capture_mut = borrowck_capture_move = capture is moved because of use here +borrowck_var_borrow_by_use_place_in_generator = + {$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in generator + +borrowck_var_borrow_by_use_place_in_closure = + {$is_single_var -> + *[true] borrow occurs + [false] borrows occur + } due to use of {$place} in closure + +borrowck_var_borrow_by_use_in_generator = + borrow occurs due to use in generator + +borrowck_var_borrow_by_use_in_closure = + borrow occurs due to use in closure + borrowck_var_move_by_use_place_in_generator = move occurs due to use of {$place} in generator borrowck_var_move_by_use_place_in_closure = move occurs due to use of {$place} in closure +borrowck_var_move_by_use_in_generator = + move occurs due to use in generator + +borrowck_var_move_by_use_in_closure = + move occurs due to use in closure + +borrowck_partial_var_move_by_use_in_generator = + variable {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to use in generator + +borrowck_partial_var_move_by_use_in_closure = + variable {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to use in closure + +borrowck_var_first_borrow_by_use_place_in_generator = + first borrow occurs due to use of {$place} in generator + +borrowck_var_first_borrow_by_use_place_in_closure = + first borrow occurs due to use of {$place} in closure + +borrowck_var_second_borrow_by_use_place_in_generator = + second borrow occurs due to use of {$place} in generator + +borrowck_var_second_borrow_by_use_place_in_closure = + second borrow occurs due to use of {$place} in closure + +borrowck_var_mutable_borrow_by_use_place_in_closure = + mutable borrow occurs due to use of {$place} in closure + borrowck_cannot_move_when_borrowed = cannot move out of {$place -> [value] value @@ -120,3 +159,90 @@ borrowck_cannot_move_when_borrowed = [value] value *[other] {$value_place} } occurs here + +borrowck_moved_due_to_call = + {$place_name} {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to this call{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_moved_due_to_usage_in_operator = + {$place_name} {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to usage in operator{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_moved_due_to_implicit_into_iter_call = + {$place_name} {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to this implicit call to `.into_iter()`{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_moved_due_to_method_call = + {$place_name} {$is_partial -> + [true] partially {""} + *[false] {""} + }moved due to this method call{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_value_moved_here = + value {$is_partial -> + [true] partially {""} + *[false] {""} + }moved{$is_move_msg -> + [true] {""} into closure + *[false] {""} + } here{$is_loop_message -> + [true] , in previous iteration of loop + *[false] {""} + } + +borrowck_consider_borrow_type_contents = + help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents + +borrowck_moved_a_fn_once_in_call = + this value implements `FnOnce`, which causes it to be moved when called + +borrowck_calling_operator_moves_lhs = + calling this operator moves the left-hand side + +borrowck_func_take_self_moved_place = + this function takes ownership of the receiver `self`, which moves {$place_name} + +borrowck_suggest_iterate_over_slice = + consider iterating over a slice of the `{$ty}`'s content to avoid moving into the `for` loop + +borrowck_suggest_create_freash_reborrow = + consider creating a fresh reborrow of {$place_name} here + +borrowck_value_capture_here = + value captured here{$is_within -> + [true] {""} by generator + *[false] {""} + } + +borrowck_move_out_place_here = + move out of {$place} occurs here + +borrowck_closure_invoked_twice = + closure cannot be invoked more than once because it moves the variable `{$place_name}` out of its environment + +borrowck_closure_moved_twice = + closure cannot be moved more than once as it is not `Copy` due to moving the variable `{$place_name}` out of its environment + +borrowck_ty_no_impl_copy = + {$is_partial_move -> + [true] partial {""} + *[false] {""} + }move occurs because {$place} has type `{$ty}`, which does not implement the `Copy` trait