summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs437
1 files changed, 298 insertions, 139 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 75a3dd0c0..15d73ed73 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,5 +1,6 @@
+use std::iter;
+
use either::Either;
-use rustc_const_eval::util::CallKind;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{
@@ -9,8 +10,8 @@ use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
-use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
+use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{
self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory,
@@ -18,20 +19,19 @@ use rustc_middle::mir::{
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty};
+use rustc_middle::util::CallKind;
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
-use rustc_span::symbol::{kw, sym};
+use rustc_span::symbol::{kw, sym, Ident};
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
use rustc_trait_selection::traits::ObligationCtxt;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
-
use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
-use crate::diagnostics::find_all_local_uses;
-use crate::diagnostics::mutability_errors::mut_borrow_of_mutable_ref;
+use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
use crate::{
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
@@ -158,7 +158,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else if reinits > 1 {
err.span_note(
MultiSpan::from_spans(reinit_spans),
- &if reinits <= 3 {
+ if reinits <= 3 {
format!("these {reinits} reinitializations might get skipped")
} else {
format!(
@@ -183,13 +183,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;
@@ -206,17 +202,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
+ let msg_opt = CapturedMessageOpt {
+ is_partial_move,
+ is_loop_message,
+ is_move_msg,
+ is_loop_move,
+ maybe_reinitialized_locations_is_empty: maybe_reinitialized_locations
+ .is_empty(),
+ };
self.explain_captures(
&mut err,
span,
move_span,
move_spans,
*moved_place,
- partially_str,
- loop_message,
- move_msg,
- is_loop_move,
- maybe_reinitialized_locations.is_empty(),
+ msg_opt,
);
}
seen_spans.insert(move_span);
@@ -253,7 +253,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// We have a `&mut` ref, we need to reborrow on each iteration (#62112).
err.span_suggestion_verbose(
span.shrink_to_lo(),
- &format!(
+ format!(
"consider creating a fresh reborrow of {} here",
self.describe_place(moved_place)
.map(|n| format!("`{n}`"))
@@ -282,12 +282,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: &note_msg,
+ span,
+ });
} else {
- None
+ err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Note {
+ is_partial_move,
+ ty,
+ place: &note_msg,
+ });
};
- self.note_type_does_not_implement_copy(&mut err, &note_msg, ty, span, partial_str);
}
if let UseSpans::FnSelfUse {
@@ -295,7 +304,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
..
} = use_spans
{
- err.note(&format!(
+ err.note(format!(
"{} occurs due to deref coercion to `{deref_target_ty}`",
desired_action.as_noun(),
));
@@ -577,7 +586,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// _ => {} // We don't want to point to this.
// };
// ```
- err.span_label(sp, &label);
+ err.span_label(sp, label);
shown = true;
}
}
@@ -633,11 +642,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let Some(default_trait) = tcx.get_diagnostic_item(sym::Default) else {
return false;
};
- // Regions are already solved, so we must use a fresh InferCtxt,
- // but the type has region variables, so erase those.
- tcx.infer_ctxt()
- .build()
- .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env)
+ self.infcx
+ .type_implements_trait(default_trait, [ty], param_env)
.must_apply_modulo_regions()
};
@@ -696,7 +702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.copied()
.find_map(find_fn_kind_from_did),
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx
- .bound_explicit_item_bounds(def_id)
+ .explicit_item_bounds(def_id)
.subst_iter_copied(tcx, substs)
.find_map(find_fn_kind_from_did),
ty::Closure(_, substs) => match substs.as_closure().kind() {
@@ -730,13 +736,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
let tcx = self.infcx.tcx;
// Try to find predicates on *generic params* that would allow copying `ty`
- let infcx = tcx.infer_ctxt().build();
-
if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
- && infcx
+ && self.infcx
.type_implements_trait(
clone_trait_def,
- [tcx.erase_regions(ty)],
+ [ty],
self.param_env,
)
.must_apply_modulo_regions()
@@ -760,12 +764,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
.and_then(|def_id| tcx.hir().get_generics(def_id))
else { return; };
// Try to find predicates on *generic params* that would allow copying `ty`
- let infcx = tcx.infer_ctxt().build();
- let ocx = ObligationCtxt::new(&infcx);
+ let ocx = ObligationCtxt::new(&self.infcx);
let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span));
let cause = ObligationCause::misc(span, self.mir_def_id());
- ocx.register_bound(cause, self.param_env, infcx.tcx.erase_regions(ty), copy_did);
+ ocx.register_bound(cause, self.param_env, ty, copy_did);
let errors = ocx.select_all_or_error();
// Only emit suggestion if all required predicates are on generic
@@ -827,11 +830,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(
@@ -868,13 +873,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 },
}
});
@@ -946,7 +953,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&msg_borrow,
None,
);
- self.suggest_binding_for_closure_capture_self(
+ self.suggest_binding_for_closure_capture_self(&mut err, &issued_spans);
+ self.suggest_using_closure_argument_instead_of_capture(
&mut err,
issued_borrow.borrowed_place,
&issued_spans,
@@ -969,6 +977,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
place,
issued_borrow.borrowed_place,
);
+ self.suggest_using_closure_argument_instead_of_capture(
+ &mut err,
+ issued_borrow.borrowed_place,
+ &issued_spans,
+ );
err
}
@@ -988,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 ";
@@ -1070,37 +1093,53 @@ 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 },
+ }
+ },
);
}
if union_type_name != "" {
- err.note(&format!(
+ err.note(format!(
"{} is a field of the union `{}`, so it overlaps the field {}",
msg_place, union_type_name, msg_borrow,
));
@@ -1199,14 +1238,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
err.span_help(
inner_call_span,
- &format!(
+ format!(
"try adding a local storing this{}...",
if use_span.is_some() { "" } else { " argument" }
),
);
err.span_help(
outer_call_span,
- &format!(
+ format!(
"...and then using that local {}",
if use_span.is_some() { "here" } else { "as the argument to this call" }
),
@@ -1229,22 +1268,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- fn suggest_binding_for_closure_capture_self(
+ /// Suggest using closure argument instead of capture.
+ ///
+ /// For example:
+ /// ```ignore (illustrative)
+ /// struct S;
+ ///
+ /// impl S {
+ /// fn call(&mut self, f: impl Fn(&mut Self)) { /* ... */ }
+ /// fn x(&self) {}
+ /// }
+ ///
+ /// let mut v = S;
+ /// v.call(|this: &mut S| v.x());
+ /// // ^\ ^-- help: try using the closure argument: `this`
+ /// // *-- error: cannot borrow `v` as mutable because it is also borrowed as immutable
+ /// ```
+ fn suggest_using_closure_argument_instead_of_capture(
&self,
err: &mut Diagnostic,
borrowed_place: Place<'tcx>,
issued_spans: &UseSpans<'tcx>,
) {
- let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
- let hir = self.infcx.tcx.hir();
+ let &UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
+ let tcx = self.infcx.tcx;
+ let hir = tcx.hir();
- // check whether the borrowed place is capturing `self` by mut reference
+ // Get the type of the local that we are trying to borrow
let local = borrowed_place.local;
- let Some(_) = self
- .body
- .local_decls
- .get(local)
- .map(|l| mut_borrow_of_mutable_ref(l, self.local_names[local])) else { return };
+ let local_ty = self.body.local_decls[local].ty;
+
+ // Get the body the error happens in
+ let Some(body_id) = hir.get(self.mir_hir_id()).body_id() else { return };
+
+ let body_expr = hir.body(body_id).value;
+
+ struct ClosureFinder<'hir> {
+ hir: rustc_middle::hir::map::Map<'hir>,
+ borrow_span: Span,
+ res: Option<(&'hir hir::Expr<'hir>, &'hir hir::Closure<'hir>)>,
+ /// The path expression with the `borrow_span` span
+ error_path: Option<(&'hir hir::Expr<'hir>, &'hir hir::QPath<'hir>)>,
+ }
+ impl<'hir> Visitor<'hir> for ClosureFinder<'hir> {
+ type NestedFilter = OnlyBodies;
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.hir
+ }
+
+ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+ if let hir::ExprKind::Path(qpath) = &ex.kind
+ && ex.span == self.borrow_span
+ {
+ self.error_path = Some((ex, qpath));
+ }
+
+ if let hir::ExprKind::Closure(closure) = ex.kind
+ && ex.span.contains(self.borrow_span)
+ // To support cases like `|| { v.call(|this| v.get()) }`
+ // FIXME: actually support such cases (need to figure out how to move from the capture place to original local)
+ && self.res.as_ref().map_or(true, |(prev_res, _)| prev_res.span.contains(ex.span))
+ {
+ self.res = Some((ex, closure));
+ }
+
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+
+ // Find the closure that most tightly wraps `capture_kind_span`
+ let mut finder =
+ ClosureFinder { hir, borrow_span: capture_kind_span, res: None, error_path: None };
+ finder.visit_expr(body_expr);
+ let Some((closure_expr, closure)) = finder.res else { return };
+
+ let typeck_results = tcx.typeck(self.mir_def_id());
+
+ // Check that the parent of the closure is a method call,
+ // with receiver matching with local's type (modulo refs)
+ let parent = hir.parent_id(closure_expr.hir_id);
+ if let hir::Node::Expr(parent) = hir.get(parent) {
+ if let hir::ExprKind::MethodCall(_, recv, ..) = parent.kind {
+ let recv_ty = typeck_results.expr_ty(recv);
+
+ if recv_ty.peel_refs() != local_ty {
+ return;
+ }
+ }
+ }
+
+ // Get closure's arguments
+ let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return };
+ let sig = substs.as_closure().sig();
+ let tupled_params =
+ tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b));
+ let ty::Tuple(params) = tupled_params.kind() else { return };
+
+ // Find the first argument with a matching type, get its name
+ let Some((_, this_name)) = params
+ .iter()
+ .zip(hir.body_param_names(closure.body))
+ .find(|(param_ty, name)|{
+ // FIXME: also support deref for stuff like `Rc` arguments
+ param_ty.peel_refs() == local_ty && name != &Ident::empty()
+ })
+ else { return };
+
+ let spans;
+ if let Some((_path_expr, qpath)) = finder.error_path
+ && let hir::QPath::Resolved(_, path) = qpath
+ && let hir::def::Res::Local(local_id) = path.res
+ {
+ // Find all references to the problematic variable in this closure body
+
+ struct VariableUseFinder {
+ local_id: hir::HirId,
+ spans: Vec<Span>,
+ }
+ impl<'hir> Visitor<'hir> for VariableUseFinder {
+ fn visit_expr(&mut self, ex: &'hir hir::Expr<'hir>) {
+ if let hir::ExprKind::Path(qpath) = &ex.kind
+ && let hir::QPath::Resolved(_, path) = qpath
+ && let hir::def::Res::Local(local_id) = path.res
+ && local_id == self.local_id
+ {
+ self.spans.push(ex.span);
+ }
+
+ hir::intravisit::walk_expr(self, ex);
+ }
+ }
+
+ let mut finder = VariableUseFinder { local_id, spans: Vec::new() };
+ finder.visit_expr(hir.body(closure.body).value);
+
+ spans = finder.spans;
+ } else {
+ spans = vec![capture_kind_span];
+ }
+
+ err.multipart_suggestion(
+ "try using the closure argument",
+ iter::zip(spans, iter::repeat(this_name.to_string())).collect(),
+ Applicability::MaybeIncorrect,
+ );
+ }
+
+ fn suggest_binding_for_closure_capture_self(
+ &self,
+ err: &mut Diagnostic,
+ issued_spans: &UseSpans<'tcx>,
+ ) {
+ let UseSpans::ClosureUse { capture_kind_span, .. } = issued_spans else { return };
+ let hir = self.infcx.tcx.hir();
struct ExpressionFinder<'hir> {
capture_span: Span,
@@ -1458,34 +1635,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
})
}
- /// Reports StorageDeadOrDrop of `place` conflicts with `borrow`.
- ///
- /// Depending on the origin of the StorageDeadOrDrop, this may be
- /// reported as either a drop or an illegal mutation of a borrowed value.
- /// The latter is preferred when the this is a drop triggered by a
- /// reassignment, as it's more user friendly to report a problem with the
- /// explicit assignment than the implicit drop.
- #[instrument(level = "debug", skip(self))]
- pub(crate) fn report_storage_dead_or_drop_of_borrowed(
- &mut self,
- location: Location,
- place_span: (Place<'tcx>, Span),
- borrow: &BorrowData<'tcx>,
- ) {
- // It's sufficient to check the last desugaring as Replace is the last
- // one to be applied.
- if let Some(DesugaringKind::Replace) = place_span.1.desugaring_kind() {
- self.report_illegal_mutation_of_borrowed(location, place_span, borrow)
- } else {
- self.report_borrowed_value_does_not_live_long_enough(
- location,
- borrow,
- place_span,
- Some(WriteKind::StorageDeadOrDrop),
- )
- }
- }
-
/// This means that some data referenced by `borrow` needs to live
/// past the point where the StorageDeadOrDrop of `place` occurs.
/// This is usually interpreted as meaning that `place` has too
@@ -1731,9 +1880,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,
@@ -1947,9 +2099,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
}
@@ -2029,7 +2184,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx;
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
- let return_ty = tcx.erase_regions(return_ty);
// to avoid panics
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
@@ -2099,7 +2253,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
err.span_suggestion_verbose(
sugg_span,
- &format!(
+ format!(
"to force the {} to take ownership of {} (and any \
other referenced variables), use the `move` keyword",
kind, captured_var
@@ -2111,7 +2265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
match category {
ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => {
let msg = format!("{} is returned here", kind);
- err.span_note(constraint_span, &msg);
+ err.span_note(constraint_span, msg);
}
ConstraintCategory::CallArgument(_) => {
fr_name.highlight_region_name(&mut err);
@@ -2122,7 +2276,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
} else {
let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
- err.span_note(constraint_span, &msg);
+ err.span_note(constraint_span, msg);
}
}
_ => bug!(
@@ -2382,11 +2536,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);
@@ -2396,11 +2553,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,
@@ -2424,7 +2583,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((method_did, method_substs)),
) = (
&self.body[loan.reserve_location.block].terminator,
- rustc_const_eval::util::find_self_call(
+ rustc_middle::util::find_self_call(
tcx,
self.body,
loan.assigned_place.local,
@@ -2439,7 +2598,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
});
if let Some(Ok(instance)) = deref_target {
let deref_target_ty = instance.ty(tcx, self.param_env);
- err.note(&format!(
+ err.note(format!(
"borrow occurs due to deref coercion to `{}`",
deref_target_ty
));
@@ -2993,7 +3152,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> {
diag.span_label(*return_span, format!("also has lifetime `{}`", region_name,));
- diag.help(&format!(
+ diag.help(format!(
"use data from the highlighted arguments which match the `{}` lifetime of \
the return type",
region_name,