summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/diagnostics
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics')
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs59
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs355
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs23
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs3
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs123
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs43
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs36
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/var_name.rs3
10 files changed, 424 insertions, 248 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 02071ed6b..1550958ab 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
use rustc_infer::infer::canonical::Canonical;
use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError;
@@ -5,14 +8,14 @@ use rustc_infer::infer::region_constraints::Constraint;
use rustc_infer::infer::region_constraints::RegionConstraintData;
use rustc_infer::infer::RegionVariableOrigin;
use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _};
-use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt};
+use rustc_infer::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::RegionVid;
use rustc_middle::ty::UniverseIndex;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::query::type_op;
-use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _};
+use rustc_trait_selection::traits::ObligationCtxt;
use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause};
use std::fmt;
@@ -158,6 +161,7 @@ trait TypeOpInfo<'tcx> {
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>;
+ #[instrument(level = "debug", skip(self, mbcx))]
fn report_error(
&self,
mbcx: &mut MirBorrowckCtxt<'_, 'tcx>,
@@ -167,6 +171,7 @@ trait TypeOpInfo<'tcx> {
) {
let tcx = mbcx.infcx.tcx;
let base_universe = self.base_universe();
+ debug!(?base_universe);
let Some(adjusted_universe) =
placeholder.universe.as_u32().checked_sub(base_universe.as_u32())
@@ -238,11 +243,11 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause);
- try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
+ let ocx = ObligationCtxt::new(&infcx);
+ type_op_prove_predicate_with_cause(&ocx, key, cause);
+ try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
}
}
@@ -279,24 +284,20 @@ where
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
-
- let mut selcx = SelectionContext::new(infcx);
+ let ocx = ObligationCtxt::new(&infcx);
// FIXME(lqd): Unify and de-duplicate the following with the actual
// `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the
// `ObligationCause`. The normalization results are currently different between
- // `AtExt::normalize` used in the query and `normalize` called below: the former fails
- // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check
- // after #85499 lands to see if its fixes have erased this difference.
+ // `QueryNormalizeExt::query_normalize` used in the query and `normalize` called below:
+ // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test.
+ // Check after #85499 lands to see if its fixes have erased this difference.
let (param_env, value) = key.into_parts();
- let Normalized { value: _, obligations } =
- rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value);
- fulfill_cx.register_predicate_obligations(infcx, obligations);
+ let _ = ocx.normalize(&cause, param_env, value.value);
- try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
+ try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
}
}
@@ -327,11 +328,11 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
- let (ref infcx, key, _) =
+ let (infcx, key, _) =
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
- let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx);
- type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?;
- try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region)
+ let ocx = ObligationCtxt::new(&infcx);
+ type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
+ try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region)
}
}
@@ -372,28 +373,28 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> {
}
}
-#[instrument(skip(fulfill_cx, infcx), level = "debug")]
+#[instrument(skip(ocx), level = "debug")]
fn try_extract_error_from_fulfill_cx<'tcx>(
- mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>,
- infcx: &InferCtxt<'tcx>,
+ ocx: &ObligationCtxt<'_, 'tcx>,
placeholder_region: ty::Region<'tcx>,
error_region: Option<ty::Region<'tcx>>,
) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> {
// We generally shouldn't have errors here because the query was
// already run, but there's no point using `delay_span_bug`
// when we're going to emit an error here anyway.
- let _errors = fulfill_cx.select_all_or_error(infcx);
- let region_constraints = infcx.with_region_constraints(|r| r.clone());
+ let _errors = ocx.select_all_or_error();
+ let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone());
try_extract_error_from_region_constraints(
- infcx,
+ ocx.infcx,
placeholder_region,
error_region,
&region_constraints,
- |vid| infcx.region_var_origin(vid),
- |vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))),
+ |vid| ocx.infcx.region_var_origin(vid),
+ |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))),
)
}
+#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))]
fn try_extract_error_from_region_constraints<'tcx>(
infcx: &InferCtxt<'tcx>,
placeholder_region: ty::Region<'tcx>,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 583bc2e28..5e3745f17 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -7,7 +7,7 @@ use rustc_errors::{
};
use rustc_hir as hir;
use rustc_hir::intravisit::{walk_block, walk_expr, Visitor};
-use rustc_hir::{AsyncGeneratorKind, GeneratorKind};
+use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ObligationCause;
use rustc_middle::mir::tcx::PlaceTy;
@@ -23,7 +23,6 @@ use rustc_span::hygiene::DesugaringKind;
use rustc_span::symbol::sym;
use rustc_span::{BytePos, Span, Symbol};
use rustc_trait_selection::infer::InferCtxtExt;
-use rustc_trait_selection::traits::TraitEngineExt as _;
use crate::borrow_set::TwoPhaseActivation;
use crate::borrowck_errors;
@@ -168,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
- self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
+ let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err);
let mut is_loop_move = false;
let mut in_pattern = false;
+ let mut seen_spans = FxHashSet::default();
for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
@@ -192,43 +192,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
is_loop_move = true;
}
- 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(),
- );
-
- if let (UseSpans::PatUse(span), []) =
- (move_spans, &maybe_reinitialized_locations[..])
- {
- if maybe_reinitialized_locations.is_empty() {
- err.span_suggestion_verbose(
- span.shrink_to_lo(),
- &format!(
- "borrow this field in the pattern to avoid moving {}",
- self.describe_place(moved_place.as_ref())
- .map(|n| format!("`{}`", n))
- .unwrap_or_else(|| "the value".to_string())
- ),
- "ref ",
- Applicability::MachineApplicable,
- );
- in_pattern = true;
+ if !seen_spans.contains(&move_span) {
+ if !closure {
+ self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern);
}
+
+ 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(),
+ );
}
+ seen_spans.insert(move_span);
}
- use_spans.var_span_label_path_only(
- &mut err,
- format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
- );
+ use_spans.var_path_only_subdiag(&mut err, desired_action);
if !is_loop_move {
err.span_label(
@@ -280,7 +265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
DescribePlaceOpt { including_downcast: true, including_tuple_field: true },
);
let note_msg = match opt_name {
- Some(ref name) => format!("`{}`", name),
+ Some(name) => format!("`{}`", name),
None => "value".to_owned(),
};
if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, &note_msg) {
@@ -321,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
+ fn suggest_ref_or_clone(
+ &mut self,
+ mpi: MovePathIndex,
+ move_span: Span,
+ err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
+ in_pattern: &mut bool,
+ ) {
+ struct ExpressionFinder<'hir> {
+ expr_span: Span,
+ expr: Option<&'hir hir::Expr<'hir>>,
+ pat: Option<&'hir hir::Pat<'hir>>,
+ parent_pat: Option<&'hir hir::Pat<'hir>>,
+ }
+ impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> {
+ fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
+ if e.span == self.expr_span {
+ self.expr = Some(e);
+ }
+ hir::intravisit::walk_expr(self, e);
+ }
+ fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) {
+ if p.span == self.expr_span {
+ self.pat = Some(p);
+ }
+ if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind {
+ if i.span == self.expr_span || p.span == self.expr_span {
+ self.pat = Some(p);
+ }
+ // Check if we are in a situation of `ident @ ident` where we want to suggest
+ // `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`.
+ if let Some(subpat) = sub && self.pat.is_none() {
+ self.visit_pat(subpat);
+ if self.pat.is_some() {
+ self.parent_pat = Some(p);
+ }
+ return;
+ }
+ }
+ hir::intravisit::walk_pat(self, p);
+ }
+ }
+ let hir = self.infcx.tcx.hir();
+ if let Some(hir::Node::Item(hir::Item {
+ kind: hir::ItemKind::Fn(_, _, body_id),
+ ..
+ })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id()))
+ && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id)
+ {
+ let place = &self.move_data.move_paths[mpi].place;
+ let span = place.as_local()
+ .map(|local| self.body.local_decls[local].source_info.span);
+ let mut finder = ExpressionFinder {
+ expr_span: move_span,
+ expr: None,
+ pat: None,
+ parent_pat: None,
+ };
+ finder.visit_expr(expr);
+ if let Some(span) = span && let Some(expr) = finder.expr {
+ for (_, expr) in hir.parent_iter(expr.hir_id) {
+ if let hir::Node::Expr(expr) = expr {
+ if expr.span.contains(span) {
+ // If the let binding occurs within the same loop, then that
+ // loop isn't relevant, like in the following, the outermost `loop`
+ // doesn't play into `x` being moved.
+ // ```
+ // loop {
+ // let x = String::new();
+ // loop {
+ // foo(x);
+ // }
+ // }
+ // ```
+ break;
+ }
+ if let hir::ExprKind::Loop(.., loop_span) = expr.kind {
+ err.span_label(loop_span, "inside of this loop");
+ }
+ }
+ }
+ let typeck = self.infcx.tcx.typeck(self.mir_def_id());
+ let hir_id = hir.get_parent_node(expr.hir_id);
+ if let Some(parent) = hir.find(hir_id) {
+ let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent
+ && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind
+ && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id)
+ {
+ (def_id.as_local(), args, 1)
+ } else if let hir::Node::Expr(parent_expr) = parent
+ && let hir::ExprKind::Call(call, args) = parent_expr.kind
+ && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind()
+ {
+ (def_id.as_local(), args, 0)
+ } else {
+ (None, &[][..], 0)
+ };
+ if let Some(def_id) = def_id
+ && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id))
+ && let Some(fn_sig) = node.fn_sig()
+ && let Some(ident) = node.ident()
+ && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id)
+ && let Some(arg) = fn_sig.decl.inputs.get(pos + offset)
+ {
+ let mut span: MultiSpan = arg.span.into();
+ span.push_span_label(
+ arg.span,
+ "this parameter takes ownership of the value".to_string(),
+ );
+ let descr = match node.fn_kind() {
+ Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function",
+ Some(hir::intravisit::FnKind::Method(..)) => "method",
+ Some(hir::intravisit::FnKind::Closure) => "closure",
+ };
+ span.push_span_label(
+ ident.span,
+ format!("in this {descr}"),
+ );
+ err.span_note(
+ span,
+ format!(
+ "consider changing this parameter type in {descr} `{ident}` to \
+ borrow instead if owning the value isn't necessary",
+ ),
+ );
+ }
+ let place = &self.move_data.move_paths[mpi].place;
+ let ty = place.ty(self.body, self.infcx.tcx).ty;
+ if let hir::Node::Expr(parent_expr) = parent
+ && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind
+ && let hir::ExprKind::Path(
+ hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _)
+ ) = call_expr.kind
+ {
+ // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing.
+ } else {
+ self.suggest_cloning(err, ty, move_span);
+ }
+ }
+ }
+ if let Some(pat) = finder.pat {
+ *in_pattern = true;
+ let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())];
+ if let Some(pat) = finder.parent_pat {
+ sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string()));
+ }
+ err.multipart_suggestion_verbose(
+ "borrow this binding in the pattern to avoid moving the value",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
+
fn report_use_of_uninitialized(
&self,
mpi: MovePathIndex,
@@ -405,10 +544,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let used = desired_action.as_general_verb_in_past_tense();
let mut err =
struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}");
- use_spans.var_span_label_path_only(
- &mut err,
- format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()),
- );
+ use_spans.var_path_only_subdiag(&mut err, desired_action);
if let InitializationRequiringAction::PartialAssignment
| InitializationRequiringAction::Assignment = desired_action
@@ -496,12 +632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// but the type has region variables, so erase those.
tcx.infer_ctxt()
.build()
- .type_implements_trait(
- default_trait,
- tcx.erase_regions(ty),
- ty::List::empty(),
- param_env,
- )
+ .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env)
.must_apply_modulo_regions()
};
@@ -535,15 +666,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx;
// Find out if the predicates show that the type is a Fn or FnMut
- let find_fn_kind_from_did =
- |predicates: ty::EarlyBinder<&[(ty::Predicate<'tcx>, Span)]>, substs| {
- predicates.0.iter().find_map(|(pred, _)| {
+ let find_fn_kind_from_did = |predicates: ty::EarlyBinder<
+ &[(ty::Predicate<'tcx>, Span)],
+ >,
+ substs| {
+ predicates.0.iter().find_map(|(pred, _)| {
let pred = if let Some(substs) = substs {
predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder()
} else {
pred.kind().skip_binder()
};
- if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred && pred.self_ty() == ty {
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
return Some(hir::Mutability::Not);
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
@@ -552,7 +685,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
None
})
- };
+ };
// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
// borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
@@ -583,25 +716,41 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let moved_place = &self.move_data.move_paths[move_out.path].place;
let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
let move_span = move_spans.args_or_use();
- let suggestion = if borrow_level == hir::Mutability::Mut {
- "&mut ".to_string()
- } else {
- "&".to_string()
- };
+ let suggestion = borrow_level.ref_prefix_str().to_owned();
(move_span.shrink_to_lo(), suggestion)
})
.collect();
err.multipart_suggestion_verbose(
- &format!(
- "consider {}borrowing {value_name}",
- if borrow_level == hir::Mutability::Mut { "mutably " } else { "" }
- ),
+ format!("consider {}borrowing {value_name}", borrow_level.mutably_str()),
sugg,
Applicability::MaybeIncorrect,
);
true
}
+ 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
+ .type_implements_trait(
+ clone_trait_def,
+ [tcx.erase_regions(ty)],
+ self.param_env,
+ )
+ .must_apply_modulo_regions()
+ {
+ err.span_suggestion_verbose(
+ span.shrink_to_hi(),
+ "consider cloning the value if the performance cost is acceptable",
+ ".clone()".to_string(),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+
fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) {
let tcx = self.infcx.tcx;
let generics = tcx.generics_of(self.mir_def_id());
@@ -613,36 +762,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
else { return; };
// Try to find predicates on *generic params* that would allow copying `ty`
let infcx = tcx.infer_ctxt().build();
- let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx);
-
- let copy_did = infcx.tcx.lang_items().copy_trait().unwrap();
+ let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span));
let cause = ObligationCause::new(
span,
self.mir_hir_id(),
rustc_infer::traits::ObligationCauseCode::MiscObligation,
);
- fulfill_cx.register_bound(
+ let errors = rustc_trait_selection::traits::fully_solve_bound(
&infcx,
+ cause,
self.param_env,
// Erase any region vids from the type, which may not be resolved
infcx.tcx.erase_regions(ty),
copy_did,
- cause,
);
- // Select all, including ambiguous predicates
- let errors = fulfill_cx.select_all_or_error(&infcx);
// Only emit suggestion if all required predicates are on generic
let predicates: Result<Vec<_>, _> = errors
.into_iter()
.map(|err| match err.obligation.predicate.kind().skip_binder() {
- PredicateKind::Trait(predicate) => match predicate.self_ty().kind() {
- ty::Param(param_ty) => Ok((
- generics.type_param(param_ty, tcx),
- predicate.trait_ref.print_only_trait_path().to_string(),
- )),
- _ => Err(()),
- },
+ PredicateKind::Clause(ty::Clause::Trait(predicate)) => {
+ match predicate.self_ty().kind() {
+ ty::Param(param_ty) => Ok((
+ generics.type_param(param_ty, tcx),
+ predicate.trait_ref.print_only_trait_path().to_string(),
+ )),
+ _ => Err(()),
+ }
+ }
_ => Err(()),
})
.collect();
@@ -678,16 +825,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let move_spans = self.move_spans(place.as_ref(), location);
let span = move_spans.args_or_use();
- let mut err =
- self.cannot_move_when_borrowed(span, &self.describe_any_place(place.as_ref()));
- err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg));
- err.span_label(span, format!("move out of {} occurs here", value_msg));
-
- borrow_spans.var_span_label_path_only(
- &mut err,
- format!("borrow occurs due to use{}", borrow_spans.describe()),
+ let mut err = self.cannot_move_when_borrowed(
+ span,
+ borrow_span,
+ &self.describe_any_place(place.as_ref()),
+ &borrow_msg,
+ &value_msg,
);
+ 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()),
@@ -729,16 +876,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
borrow_span,
&self.describe_any_place(borrow.borrowed_place.as_ref()),
);
-
- borrow_spans.var_span_label(
- &mut err,
- {
- let place = &borrow.borrowed_place;
- let desc_place = self.describe_any_place(place.as_ref());
- format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe())
- },
- "mutable",
- );
+ borrow_spans.var_subdiag(&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 },
+ }
+ });
self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic(
@@ -1271,7 +1417,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// then just use the normal error. The closure isn't escaping
// and `move` will not help here.
(
- Some(ref name),
+ Some(name),
BorrowExplanation::MustBeValidFor {
category:
category @ (ConstraintCategory::Return(_)
@@ -1292,7 +1438,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
&format!("`{}`", name),
),
(
- ref name,
+ name,
BorrowExplanation::MustBeValidFor {
category: ConstraintCategory::Assignment,
from_closure: false,
@@ -1304,7 +1450,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
span,
..
},
- ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span),
+ ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span),
(Some(name), explanation) => self.report_local_value_does_not_live_long_enough(
location,
&name,
@@ -1556,7 +1702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
- err.span_label(proper_span, "creates a temporary which is freed while still in use");
+ err.span_label(proper_span, "creates a temporary value which is freed while still in use");
err.span_label(drop_span, "temporary value is freed at the end of this statement");
match explanation {
@@ -1719,7 +1865,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
err.span_label(borrow_span, note);
let tcx = self.infcx.tcx;
- let ty_params = ty::List::empty();
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
let return_ty = tcx.erase_regions(return_ty);
@@ -1728,7 +1873,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator)
&& self
.infcx
- .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env)
+ .type_implements_trait(iter_trait, [return_ty], self.param_env)
.must_apply_modulo_regions()
{
err.span_suggestion_hidden(
@@ -2307,7 +2452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// and it'll make sense.
let location = borrow.reserve_location;
debug!("annotate_argument_and_return_for_borrow: location={:?}", location);
- if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) =
+ if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) =
&self.body[location.block].statements.get(location.statement_index)
{
debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation);
@@ -2335,8 +2480,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Check if our `target` was captured by a closure.
if let Rvalue::Aggregate(
box AggregateKind::Closure(def_id, substs),
- ref operands,
- ) = *rvalue
+ operands,
+ ) = rvalue
{
for operand in operands {
let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else {
@@ -2360,7 +2505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// into a place then we should annotate the closure in
// case it ends up being assigned into the return place.
annotated_closure =
- self.annotate_fn_sig(def_id, substs.as_closure().sig());
+ self.annotate_fn_sig(*def_id, substs.as_closure().sig());
debug!(
"annotate_argument_and_return_for_borrow: \
annotated_closure={:?} assigned_from_local={:?} \
@@ -2527,7 +2672,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind {
// With access to the lifetime, we can get
// the span of it.
- arguments.push((*argument, lifetime.span));
+ arguments.push((*argument, lifetime.ident.span));
} else {
bug!("ty type is a ref but hir type is not");
}
@@ -2546,7 +2691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut return_span = fn_decl.output.span();
if let hir::FnRetTy::Return(ty) = &fn_decl.output {
if let hir::TyKind::Rptr(lifetime, _) = ty.kind {
- return_span = lifetime.span;
+ return_span = lifetime.ident.span;
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index 582d683dd..304683618 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -469,8 +469,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else if self.was_captured_by_trait_object(borrow) {
LaterUseKind::TraitCapture
} else if location.statement_index == block.statements.len() {
- if let TerminatorKind::Call { ref func, from_hir_call: true, .. } =
- block.terminator().kind
+ if let TerminatorKind::Call { func, from_hir_call: true, .. } =
+ &block.terminator().kind
{
// Just point to the function, to reduce the chance of overlapping spans.
let function_span = match func {
@@ -515,19 +515,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// will only ever have one item at any given time, but by using a vector, we can pop from
// it which simplifies the termination logic.
let mut queue = vec![location];
- let mut target = if let Some(&Statement {
- kind: StatementKind::Assign(box (ref place, _)),
- ..
- }) = stmt
- {
- if let Some(local) = place.as_local() {
- local
+ let mut target =
+ if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt {
+ if let Some(local) = place.as_local() {
+ local
+ } else {
+ return false;
+ }
} else {
return false;
- }
- } else {
- return false;
- };
+ };
debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue);
while let Some(current_location) = queue.pop() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
index b3edc35dc..498e98343 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
use std::collections::BTreeSet;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index b5a3081e5..15f42e26c 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
use std::collections::VecDeque;
use std::rc::Rc;
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 534d9ecae..4e2271a30 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
location: Location,
place: PlaceRef<'tcx>,
diag: &mut Diagnostic,
- ) {
+ ) -> bool {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
let mut target = place.local_or_deref_local();
for stmt in &self.body[location.block].statements[location.statement_index..] {
@@ -78,7 +78,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind {
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
match from {
- Operand::Copy(ref place) | Operand::Move(ref place)
+ Operand::Copy(place) | Operand::Move(place)
if target == place.local_or_deref_local() =>
{
target = into.local_or_deref_local()
@@ -101,12 +101,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("add_moved_or_invoked_closure_note: id={:?}", id);
if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() {
- Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place))
+ Some(Operand::Copy(place) | Operand::Move(place))
if target == place.local_or_deref_local() =>
{
place.local_or_deref_local().unwrap()
}
- _ => return,
+ _ => return false,
};
debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
@@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
- return;
+ return true;
}
}
}
@@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
ty::place_to_string_for_capture(self.infcx.tcx, hir_place)
),
);
+ return true;
}
}
}
+ false
}
/// End-user visible description of `place` if one can be found.
@@ -350,7 +352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
} else {
def.non_enum_variant()
};
- if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn {
+ if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) {
return None;
}
Some(variant.fields[field.index()].name.to_string())
@@ -437,9 +439,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if !is_terminator {
continue;
} else if let Some(Terminator {
- kind: TerminatorKind::Call { ref func, from_hir_call: false, .. },
+ kind: TerminatorKind::Call { func, from_hir_call: false, .. },
..
- }) = bbd.terminator
+ }) = &bbd.terminator
{
if let Some(source) =
BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx)
@@ -588,22 +590,45 @@ impl UseSpans<'_> {
}
}
- // Add a span label to the arguments of the closure, if it exists.
+ /// Add a span label to the arguments of the closure, if it exists.
pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) {
if let UseSpans::ClosureUse { args_span, .. } = self {
err.span_label(args_span, message);
}
}
- // Add a span label to the use of the captured variable, if it exists.
- // only adds label to the `path_span`
- pub(super) fn var_span_label_path_only(self, err: &mut Diagnostic, message: impl Into<String>) {
- if let UseSpans::ClosureUse { path_span, .. } = self {
- err.span_label(path_span, message);
+ /// Add a span label to the use of the captured variable, if it exists.
+ /// only adds label to the `path_span`
+ pub(super) fn var_path_only_subdiag(
+ self,
+ err: &mut Diagnostic,
+ action: crate::InitializationRequiringAction,
+ ) {
+ use crate::session_diagnostics::CaptureVarPathUseCause::*;
+ use crate::InitializationRequiringAction::*;
+ if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self {
+ match generator_kind {
+ Some(_) => {
+ err.subdiagnostic(match action {
+ Borrow => BorrowInGenerator { path_span },
+ MatchOn | Use => UseInGenerator { path_span },
+ Assignment => AssignInGenerator { path_span },
+ PartialAssignment => AssignPartInGenerator { path_span },
+ });
+ }
+ None => {
+ err.subdiagnostic(match action {
+ Borrow => BorrowInClosure { path_span },
+ MatchOn | Use => UseInClosure { path_span },
+ Assignment => AssignInClosure { path_span },
+ PartialAssignment => AssignPartInClosure { path_span },
+ });
+ }
+ }
}
}
- // Add a span label to the use of the captured variable, if it exists.
+ /// Add a span label to the use of the captured variable, if it exists.
pub(super) fn var_span_label(
self,
err: &mut Diagnostic,
@@ -623,6 +648,35 @@ impl UseSpans<'_> {
}
}
+ /// Add a subdiagnostic to the use of the captured variable, if it exists.
+ pub(super) fn var_subdiag(
+ self,
+ err: &mut Diagnostic,
+ kind: Option<rustc_middle::mir::BorrowKind>,
+ f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause,
+ ) {
+ use crate::session_diagnostics::CaptureVarKind::*;
+ if let UseSpans::ClosureUse { generator_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::Shallow
+ | rustc_middle::mir::BorrowKind::Unique => {
+ Immute { kind_span: capture_kind_span }
+ }
+
+ rustc_middle::mir::BorrowKind::Mut { .. } => {
+ Mut { kind_span: capture_kind_span }
+ }
+ },
+ None => Move { kind_span: capture_kind_span },
+ });
+ };
+ err.subdiagnostic(f(generator_kind, path_span));
+ }
+ }
+
/// Returns `false` if this place is not used in a closure.
pub(super) fn for_closure(&self) -> bool {
match *self {
@@ -757,33 +811,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
};
debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt);
- if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind {
- match **kind {
- AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => {
- debug!("move_spans: def_id={:?} places={:?}", def_id, places);
- if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
- self.closure_span(def_id, moved_place, places)
- {
- return ClosureUse {
- generator_kind,
- args_span,
- capture_kind_span,
- path_span,
- };
- }
- }
- _ => {}
+ if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind
+ && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind
+ {
+ debug!("move_spans: def_id={:?} places={:?}", def_id, places);
+ if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
+ self.closure_span(def_id, moved_place, places)
+ {
+ return ClosureUse {
+ generator_kind,
+ args_span,
+ capture_kind_span,
+ path_span,
+ };
}
}
// StatementKind::FakeRead only contains a def_id if they are introduced as a result
// of pattern matching within a closure.
- if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind {
+ if let StatementKind::FakeRead(box (cause, place)) = stmt.kind {
match cause {
FakeReadCause::ForMatchedPlace(Some(closure_def_id))
| FakeReadCause::ForLet(Some(closure_def_id)) => {
debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place);
- let places = &[Operand::Move(*place)];
+ let places = &[Operand::Move(place)];
if let Some((args_span, generator_kind, capture_kind_span, path_span)) =
self.closure_span(closure_def_id, moved_place, places)
{
@@ -870,7 +921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
debug!("borrow_spans: use_span={:?} location={:?}", use_span, location);
let target = match self.body[location.block].statements.get(location.statement_index) {
- Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => {
+ Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => {
if let Some(local) = place.as_local() {
local
} else {
@@ -886,9 +937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
for stmt in &self.body[location.block].statements[location.statement_index + 1..] {
- if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) =
- stmt.kind
- {
+ if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind {
let (&def_id, is_generator) = match kind {
box AggregateKind::Closure(def_id, _) => (def_id, false),
box AggregateKind::Generator(def_id, _, _) => (def_id, true),
diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
index 8ad40c0aa..3319a8068 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
@@ -1,6 +1,4 @@
-use rustc_errors::{
- Applicability, Diagnostic, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed,
-};
+use rustc_errors::{Applicability, Diagnostic};
use rustc_hir as hir;
use rustc_hir::intravisit::Visitor;
use rustc_hir::Node;
@@ -221,8 +219,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
PlaceRef {
local,
projection:
- &[
- ref proj_base @ ..,
+ [
+ proj_base @ ..,
ProjectionElem::Deref,
ProjectionElem::Field(field, _),
ProjectionElem::Deref,
@@ -233,7 +231,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
if let Some(span) = get_mut_span_in_struct_field(
self.infcx.tcx,
Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty,
- field,
+ *field,
) {
err.span_suggestion_verbose(
span,
@@ -391,13 +389,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// diagnostic: if the span starts with a mutable borrow of
// a local variable, then just suggest the user remove it.
PlaceRef { local: _, projection: [] }
- if {
- if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) {
- snippet.starts_with("&mut ")
- } else {
- false
- }
- } =>
+ if self
+ .infcx
+ .tcx
+ .sess
+ .source_map()
+ .span_to_snippet(span)
+ .map_or(false, |snippet| snippet.starts_with("&mut ")) =>
{
err.span_label(span, format!("cannot {ACT}", ACT = act));
err.span_suggestion(
@@ -629,25 +627,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
self.buffer_error(err);
}
- fn suggest_map_index_mut_alternatives(
- &self,
- ty: Ty<'_>,
- err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
- span: Span,
- ) {
+ fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) {
let Some(adt) = ty.ty_adt_def() else { return };
let did = adt.did();
if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did)
|| self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did)
{
- struct V<'a, 'b, 'tcx, G: EmissionGuarantee> {
+ struct V<'a, 'tcx> {
assign_span: Span,
- err: &'a mut DiagnosticBuilder<'b, G>,
+ err: &'a mut Diagnostic,
ty: Ty<'tcx>,
suggested: bool,
}
- impl<'a, 'b: 'a, 'hir, 'tcx, G: EmissionGuarantee> Visitor<'hir> for V<'a, 'b, 'tcx, G> {
- fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) {
+ impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
+ fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
hir::intravisit::walk_stmt(self, stmt);
let expr = match stmt.kind {
hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr,
@@ -705,7 +698,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
),
(rv.span.shrink_to_hi(), ")".to_string()),
],
- ].into_iter(),
+ ],
Applicability::MachineApplicable,
);
self.suggested = true;
@@ -1218,7 +1211,7 @@ fn get_mut_span_in_struct_field<'tcx>(
&& let hir::Node::Field(field) = node
&& let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind
{
- return Some(lt.span.between(ty.span));
+ return Some(lt.ident.span.between(ty.span));
}
None
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 15230718d..9bc2e79e2 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -2,7 +2,7 @@
#![deny(rustc::diagnostic_outside_of_impl)]
//! Error reporting machinery for lifetime errors.
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
use rustc_hir::def_id::DefId;
use rustc_hir::intravisit::Visitor;
@@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::Region;
use rustc_middle::ty::TypeVisitor;
use rustc_middle::ty::{self, RegionVid, Ty};
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, Ident};
use rustc_span::Span;
use crate::borrowck_errors;
@@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
// Try to convert the lower-bound region into something named we can print for the user.
let lower_bound_region = self.to_error_region(type_test.lower_bound);
- let type_test_span = type_test.locations.span(&self.body);
+ let type_test_span = type_test.span;
if let Some(lower_bound_region) = lower_bound_region {
let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx);
@@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fn get_impl_ident_and_self_ty_from_trait(
&self,
def_id: DefId,
- trait_objects: &FxHashSet<DefId>,
+ trait_objects: &FxIndexSet<DefId>,
) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> {
let tcx = self.infcx.tcx;
match tcx.hir().get_if_local(def_id) {
@@ -514,9 +514,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
span: *span,
ty_err: match output_ty.kind() {
ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span },
- ty::Adt(def, _)
- if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) =>
- {
+ ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => {
FnMutReturnTypeErr::ReturnAsyncBlock { span: *span }
}
_ => FnMutReturnTypeErr::ReturnRef { span: *span },
@@ -830,7 +828,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
};
debug!(?param);
- let mut visitor = TraitObjectVisitor(FxHashSet::default());
+ let mut visitor = TraitObjectVisitor(FxIndexSet::default());
visitor.visit_ty(param.param_ty);
let Some((ident, self_ty)) =
@@ -843,7 +841,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
fn suggest_constrain_dyn_trait_in_impl(
&self,
err: &mut Diagnostic,
- found_dids: &FxHashSet<DefId>,
+ found_dids: &FxIndexSet<DefId>,
ident: Ident,
self_ty: &hir::Ty<'_>,
) -> bool {
@@ -923,14 +921,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
}
}
hir::ExprKind::Block(blk, _) => {
- if let Some(ref expr) = blk.expr {
+ if let Some(expr) = blk.expr {
// only when the block is a closure
if let hir::ExprKind::Closure(hir::Closure {
capture_clause: hir::CaptureBy::Ref,
+ body,
..
}) = expr.kind
{
- closure_span = Some(expr.span.shrink_to_lo());
+ let body = map.body(*body);
+ if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) {
+ closure_span = Some(expr.span.shrink_to_lo());
+ }
}
}
}
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index c044dbaba..171e62d91 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -254,7 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
.or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr))
.or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr));
- if let Some(ref value) = value {
+ if let Some(value) = &value {
self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone());
}
@@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
})
}
- ty::BoundRegionKind::BrAnon(_) => None,
+ ty::BoundRegionKind::BrAnon(..) => None,
},
ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None,
@@ -576,30 +576,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
let args = last_segment.args.as_ref()?;
let lifetime =
self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?;
- match lifetime.name {
- hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error)
- | hir::LifetimeName::Error
- | hir::LifetimeName::Static => {
- let lifetime_span = lifetime.span;
- Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span))
- }
-
- hir::LifetimeName::Param(_, hir::ParamName::Fresh)
- | hir::LifetimeName::ImplicitObjectLifetimeDefault
- | hir::LifetimeName::Infer => {
- // In this case, the user left off the lifetime; so
- // they wrote something like:
- //
- // ```
- // x: Foo<T>
- // ```
- //
- // where the fully elaborated form is `Foo<'_, '1,
- // T>`. We don't consider this a match; instead we let
- // the "fully elaborated" type fallback above handle
- // it.
- None
- }
+ if lifetime.is_anonymous() {
+ None
+ } else {
+ Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span))
}
}
@@ -959,8 +939,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
{
predicates.iter().any(|pred| {
match pred.kind().skip_binder() {
- ty::PredicateKind::Trait(data) if data.self_ty() == ty => {}
- ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {}
+ ty::PredicateKind::Clause(ty::Clause::Trait(data)) if data.self_ty() == ty => {}
+ ty::PredicateKind::Clause(ty::Clause::Projection(data)) if data.projection_ty.self_ty() == ty => {}
_ => return false,
}
tcx.any_free_region_meets(pred, |r| {
diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
index 9ba29f04b..b385f95b6 100644
--- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
use crate::Upvar;
use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
use rustc_index::vec::{Idx, IndexVec};