summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs10
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs13
-rw-r--r--compiler/rustc_borrowck/src/constraint_generation.rs2
-rw-r--r--compiler/rustc_borrowck/src/constraints/graph.rs1
-rw-r--r--compiler/rustc_borrowck/src/constraints/mod.rs6
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs12
-rw-r--r--compiler/rustc_borrowck/src/def_use.rs2
-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
-rw-r--r--compiler/rustc_borrowck/src/facts.rs2
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs67
-rw-r--r--compiler/rustc_borrowck/src/lib.rs115
-rw-r--r--compiler/rustc_borrowck/src/location.rs2
-rw-r--r--compiler/rustc_borrowck/src/member_constraints.rs4
-rw-r--r--compiler/rustc_borrowck/src/nll.rs19
-rw-r--r--compiler/rustc_borrowck/src/path_utils.rs2
-rw-r--r--compiler/rustc_borrowck/src/place_ext.rs2
-rw-r--r--compiler/rustc_borrowck/src/places_conflict.rs16
-rw-r--r--compiler/rustc_borrowck/src/prefixes.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs5
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs175
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs119
-rw-r--r--compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs2
-rw-r--r--compiler/rustc_borrowck/src/renumber.rs2
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs94
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs13
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs82
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs5
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs200
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs17
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs133
-rw-r--r--compiler/rustc_borrowck/src/used_muts.rs2
45 files changed, 1018 insertions, 797 deletions
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 41279588e..5bb92a358 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::nll::ToRegionVid;
use crate::path_utils::allow_two_phase_borrow;
use crate::place_ext::PlaceExt;
@@ -196,7 +198,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
rvalue: &mir::Rvalue<'tcx>,
location: mir::Location,
) {
- if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
+ if let &mir::Rvalue::Ref(region, kind, borrowed_place) = rvalue {
if borrowed_place.ignore_borrow(self.tcx, self.body, &self.locals_state_at_exit) {
debug!("ignoring_borrow of {:?}", borrowed_place);
return;
@@ -209,7 +211,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
region,
reserve_location: location,
activation_location: TwoPhaseActivation::NotTwoPhase,
- borrowed_place: *borrowed_place,
+ borrowed_place,
assigned_place: *assigned_place,
};
let (idx, _) = self.location_map.insert_full(location, borrow);
@@ -271,14 +273,14 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'tcx> {
}
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) {
- if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue {
+ if let &mir::Rvalue::Ref(region, kind, place) = rvalue {
// double-check that we already registered a BorrowData for this
let borrow_data = &self.location_map[&location];
assert_eq!(borrow_data.reserve_location, location);
assert_eq!(borrow_data.kind, kind);
assert_eq!(borrow_data.region, region.to_region_vid());
- assert_eq!(borrow_data.borrowed_place, *place);
+ assert_eq!(borrow_data.borrowed_place, place);
}
self.super_rvalue(rvalue, location)
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index 08ea00d71..01be37912 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -8,9 +8,18 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
pub(crate) fn cannot_move_when_borrowed(
&self,
span: Span,
- desc: &str,
+ borrow_span: Span,
+ place: &str,
+ borrow_place: &str,
+ value_place: &str,
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
- struct_span_err!(self, span, E0505, "cannot move out of {} because it is borrowed", desc,)
+ self.infcx.tcx.sess.create_err(crate::session_diagnostics::MoveBorrow {
+ place,
+ span,
+ borrow_place,
+ value_place,
+ borrow_span,
+ })
}
pub(crate) fn cannot_use_when_mutably_borrowed(
diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs
index f185e402f..11b31c3f1 100644
--- a/compiler/rustc_borrowck/src/constraint_generation.rs
+++ b/compiler/rustc_borrowck/src/constraint_generation.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_infer::infer::InferCtxt;
use rustc_middle::mir::visit::TyContext;
use rustc_middle::mir::visit::Visitor;
diff --git a/compiler/rustc_borrowck/src/constraints/graph.rs b/compiler/rustc_borrowck/src/constraints/graph.rs
index 609fbc2bc..385f15317 100644
--- a/compiler/rustc_borrowck/src/constraints/graph.rs
+++ b/compiler/rustc_borrowck/src/constraints/graph.rs
@@ -163,6 +163,7 @@ impl<'s, 'tcx, D: ConstraintGraphDirecton> Iterator for Edges<'s, 'tcx, D> {
span: DUMMY_SP,
category: ConstraintCategory::Internal,
variance_info: VarianceDiagInfo::default(),
+ from_closure: false,
})
} else {
None
diff --git a/compiler/rustc_borrowck/src/constraints/mod.rs b/compiler/rustc_borrowck/src/constraints/mod.rs
index df0412813..84a93e5f7 100644
--- a/compiler/rustc_borrowck/src/constraints/mod.rs
+++ b/compiler/rustc_borrowck/src/constraints/mod.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
use rustc_data_structures::graph::scc::Sccs;
use rustc_index::vec::IndexVec;
use rustc_middle::mir::ConstraintCategory;
@@ -96,6 +99,9 @@ pub struct OutlivesConstraint<'tcx> {
/// Variance diagnostic information
pub variance_info: VarianceDiagInfo<'tcx>,
+
+ /// If this constraint is promoted from closure requirements.
+ pub from_closure: bool,
}
impl<'tcx> fmt::Debug for OutlivesConstraint<'tcx> {
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index b162095f8..86da767f3 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! This file provides API for compiler consumers.
use rustc_hir::def_id::LocalDefId;
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 9f7a4d499..f825b1d8f 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::fx::FxHashMap;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
@@ -356,9 +358,9 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
stmt: &mir::Statement<'tcx>,
location: Location,
) {
- match stmt.kind {
- mir::StatementKind::Assign(box (lhs, ref rhs)) => {
- if let mir::Rvalue::Ref(_, _, place) = *rhs {
+ match &stmt.kind {
+ mir::StatementKind::Assign(box (lhs, rhs)) => {
+ if let mir::Rvalue::Ref(_, _, place) = rhs {
if place.ignore_borrow(
self.tcx,
self.body,
@@ -375,13 +377,13 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
// Make sure there are no remaining borrows for variables
// that are assigned over.
- self.kill_borrows_on_place(trans, lhs);
+ self.kill_borrows_on_place(trans, *lhs);
}
mir::StatementKind::StorageDead(local) => {
// Make sure there are no remaining borrows for locals that
// are gone out of scope.
- self.kill_borrows_on_place(trans, Place::from(local));
+ self.kill_borrows_on_place(trans, Place::from(*local));
}
mir::StatementKind::FakeRead(..)
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index a5c0d7742..8e62a0198 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_middle::mir::visit::{
MutatingUseContext, NonMutatingUseContext, NonUseContext, PlaceContext,
};
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};
diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs
index 22134d5a7..51ed27c16 100644
--- a/compiler/rustc_borrowck/src/facts.rs
+++ b/compiler/rustc_borrowck/src/facts.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::location::{LocationIndex, LocationTable};
use crate::BorrowIndex;
use polonius_engine::AllFacts as PoloniusFacts;
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 3157f861d..f66a7ab3c 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, BasicBlock, Body, Location, NonDivergingIntrinsic, Place, Rvalue};
@@ -67,9 +69,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.consume_operand(location, op);
}
StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(mir::CopyNonOverlapping {
- ref src,
- ref dst,
- ref count,
+ src,
+ dst,
+ count,
})) => {
self.consume_operand(location, src);
self.consume_operand(location, dst);
@@ -104,7 +106,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.check_activations(location);
match &terminator.kind {
- TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+ TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
self.consume_operand(location, discr);
}
TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
@@ -117,7 +119,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
TerminatorKind::DropAndReplace {
place: drop_place,
- value: ref new_value,
+ value: new_value,
target: _,
unwind: _,
} => {
@@ -125,8 +127,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
self.consume_operand(location, new_value);
}
TerminatorKind::Call {
- ref func,
- ref args,
+ func,
+ args,
destination,
target: _,
cleanup: _,
@@ -139,15 +141,15 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
self.mutate_place(location, *destination, Deep);
}
- TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+ TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
self.consume_operand(location, cond);
use rustc_middle::mir::AssertKind;
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
self.consume_operand(location, len);
self.consume_operand(location, index);
}
}
- TerminatorKind::Yield { ref value, resume, resume_arg, drop: _ } => {
+ TerminatorKind::Yield { value, resume, resume_arg, drop: _ } => {
self.consume_operand(location, value);
// Invalidate all borrows of local places
@@ -173,25 +175,25 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
TerminatorKind::InlineAsm {
template: _,
- ref operands,
+ operands,
options: _,
line_spans: _,
destination: _,
cleanup: _,
} => {
for op in operands {
- match *op {
- InlineAsmOperand::In { reg: _, ref value } => {
+ match op {
+ InlineAsmOperand::In { reg: _, value } => {
self.consume_operand(location, value);
}
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
- if let Some(place) = place {
+ if let &Some(place) = place {
self.mutate_place(location, place, Shallow(None));
}
}
- InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+ InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
self.consume_operand(location, in_value);
- if let Some(out_place) = out_place {
+ if let &Some(out_place) = out_place {
self.mutate_place(location, out_place, Shallow(None));
}
}
@@ -250,8 +252,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
// Simulates consumption of an rvalue
fn consume_rvalue(&mut self, location: Location, rvalue: &Rvalue<'tcx>) {
- match *rvalue {
- Rvalue::Ref(_ /*rgn*/, bk, place) => {
+ match rvalue {
+ &Rvalue::Ref(_ /*rgn*/, bk, place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -270,7 +272,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
}
- Rvalue::AddressOf(mutability, place) => {
+ &Rvalue::AddressOf(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
Deep,
@@ -286,20 +288,19 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
Rvalue::ThreadLocalRef(_) => {}
- Rvalue::Use(ref operand)
- | Rvalue::Repeat(ref operand, _)
- | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
- | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
- self.consume_operand(location, operand)
- }
- Rvalue::CopyForDeref(ref place) => {
- let op = &Operand::Copy(*place);
+ Rvalue::Use(operand)
+ | Rvalue::Repeat(operand, _)
+ | Rvalue::UnaryOp(_ /*un_op*/, operand)
+ | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
+
+ &Rvalue::CopyForDeref(place) => {
+ let op = &Operand::Copy(place);
self.consume_operand(location, op);
}
- Rvalue::Len(place) | Rvalue::Discriminant(place) => {
- let af = match *rvalue {
+ &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
+ let af = match rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
_ => unreachable!(),
@@ -312,15 +313,15 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
);
}
- Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
- | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+ Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+ | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, operand1);
self.consume_operand(location, operand2);
}
Rvalue::NullaryOp(_op, _ty) => {}
- Rvalue::Aggregate(_, ref operands) => {
+ Rvalue::Aggregate(_, operands) => {
for operand in operands {
self.consume_operand(location, operand);
}
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index abfe253d4..74b4e4a0c 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -18,7 +18,8 @@ extern crate tracing;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::dominators::Dominators;
-use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_data_structures::vec_map::VecMap;
+use rustc_errors::{Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_hir::def_id::LocalDefId;
use rustc_index::bit_set::ChunkedBitSet;
@@ -82,7 +83,7 @@ mod type_check;
mod universal_regions;
mod used_muts;
-// A public API provided for the Rust compiler consumers.
+/// A public API provided for the Rust compiler consumers.
pub mod consumers;
use borrow_set::{BorrowData, BorrowSet};
@@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>(
) -> &'tcx BorrowCheckResult<'tcx> {
let (input_body, promoted) = tcx.mir_promoted(def);
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
+
+ if input_body.borrow().should_skip() {
+ debug!("Skipping borrowck because of injected body");
+ // Let's make up a borrowck result! Fun times!
+ let result = BorrowCheckResult {
+ concrete_opaque_types: VecMap::new(),
+ closure_requirements: None,
+ used_mut_upvars: SmallVec::new(),
+ tainted_by_errors: None,
+ };
+ return tcx.arena.alloc(result);
+ }
+
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
let infcx =
@@ -178,13 +192,13 @@ fn do_mir_borrowck<'tcx>(
}
}
- let mut errors = error::BorrowckErrors::new();
+ let mut errors = error::BorrowckErrors::new(infcx.tcx);
// Gather the upvars of a closure, if any.
let tables = tcx.typeck_opt_const_arg(def);
- if let Some(ErrorGuaranteed { .. }) = tables.tainted_by_errors {
- infcx.set_tainted_by_errors();
- errors.set_tainted_by_errors();
+ if let Some(e) = tables.tainted_by_errors {
+ infcx.set_tainted_by_errors(e);
+ errors.set_tainted_by_errors(e);
}
let upvars: Vec<_> = tables
.closure_min_captures_flattened(def.did)
@@ -564,12 +578,12 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
self.check_activations(location, span, flow_state);
match &stmt.kind {
- StatementKind::Assign(box (lhs, ref rhs)) => {
+ StatementKind::Assign(box (lhs, rhs)) => {
self.consume_rvalue(location, (rhs, span), flow_state);
self.mutate_place(location, (*lhs, span), Shallow(None), flow_state);
}
- StatementKind::FakeRead(box (_, ref place)) => {
+ StatementKind::FakeRead(box (_, place)) => {
// Read for match doesn't access any memory and is used to
// assert that a place is safe and live. So we don't have to
// do any checks here.
@@ -587,7 +601,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
flow_state,
);
}
- StatementKind::Intrinsic(box ref kind) => match kind {
+ StatementKind::Intrinsic(box kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.consume_operand(location, (op, span), flow_state),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
span,
@@ -629,8 +643,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
self.check_activations(loc, span, flow_state);
- match term.kind {
- TerminatorKind::SwitchInt { ref discr, switch_ty: _, targets: _ } => {
+ match &term.kind {
+ TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
self.consume_operand(loc, (discr, span), flow_state);
}
TerminatorKind::Drop { place, target: _, unwind: _ } => {
@@ -642,7 +656,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
self.access_place(
loc,
- (place, span),
+ (*place, span),
(AccessDepth::Drop, Write(WriteKind::StorageDeadOrDrop)),
LocalMutationIsAllowed::Yes,
flow_state,
@@ -650,16 +664,16 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
TerminatorKind::DropAndReplace {
place: drop_place,
- value: ref new_value,
+ value: new_value,
target: _,
unwind: _,
} => {
- self.mutate_place(loc, (drop_place, span), Deep, flow_state);
+ self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
self.consume_operand(loc, (new_value, span), flow_state);
}
TerminatorKind::Call {
- ref func,
- ref args,
+ func,
+ args,
destination,
target: _,
cleanup: _,
@@ -670,43 +684,43 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
for arg in args {
self.consume_operand(loc, (arg, span), flow_state);
}
- self.mutate_place(loc, (destination, span), Deep, flow_state);
+ self.mutate_place(loc, (*destination, span), Deep, flow_state);
}
- TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
+ TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
self.consume_operand(loc, (cond, span), flow_state);
use rustc_middle::mir::AssertKind;
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
self.consume_operand(loc, (len, span), flow_state);
self.consume_operand(loc, (index, span), flow_state);
}
}
- TerminatorKind::Yield { ref value, resume: _, resume_arg, drop: _ } => {
+ TerminatorKind::Yield { value, resume: _, resume_arg, drop: _ } => {
self.consume_operand(loc, (value, span), flow_state);
- self.mutate_place(loc, (resume_arg, span), Deep, flow_state);
+ self.mutate_place(loc, (*resume_arg, span), Deep, flow_state);
}
TerminatorKind::InlineAsm {
template: _,
- ref operands,
+ operands,
options: _,
line_spans: _,
destination: _,
cleanup: _,
} => {
for op in operands {
- match *op {
- InlineAsmOperand::In { reg: _, ref value } => {
+ match op {
+ InlineAsmOperand::In { reg: _, value } => {
self.consume_operand(loc, (value, span), flow_state);
}
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
if let Some(place) = place {
- self.mutate_place(loc, (place, span), Shallow(None), flow_state);
+ self.mutate_place(loc, (*place, span), Shallow(None), flow_state);
}
}
- InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
+ InlineAsmOperand::InOut { reg: _, late: _, in_value, out_place } => {
self.consume_operand(loc, (in_value, span), flow_state);
- if let Some(out_place) = out_place {
+ if let &Some(out_place) = out_place {
self.mutate_place(
loc,
(out_place, span),
@@ -1150,8 +1164,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(rvalue, span): (&'cx Rvalue<'tcx>, Span),
flow_state: &Flows<'cx, 'tcx>,
) {
- match *rvalue {
- Rvalue::Ref(_ /*rgn*/, bk, place) => {
+ match rvalue {
+ &Rvalue::Ref(_ /*rgn*/, bk, place) => {
let access_kind = match bk {
BorrowKind::Shallow => {
(Shallow(Some(ArtificialField::ShallowBorrow)), Read(ReadKind::Borrow(bk)))
@@ -1189,7 +1203,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
- Rvalue::AddressOf(mutability, place) => {
+ &Rvalue::AddressOf(mutability, place) => {
let access_kind = match mutability {
Mutability::Mut => (
Deep,
@@ -1218,14 +1232,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Rvalue::ThreadLocalRef(_) => {}
- Rvalue::Use(ref operand)
- | Rvalue::Repeat(ref operand, _)
- | Rvalue::UnaryOp(_ /*un_op*/, ref operand)
- | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/)
- | Rvalue::ShallowInitBox(ref operand, _ /*ty*/) => {
+ Rvalue::Use(operand)
+ | Rvalue::Repeat(operand, _)
+ | Rvalue::UnaryOp(_ /*un_op*/, operand)
+ | Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
+ | Rvalue::ShallowInitBox(operand, _ /*ty*/) => {
self.consume_operand(location, (operand, span), flow_state)
}
- Rvalue::CopyForDeref(place) => {
+
+ &Rvalue::CopyForDeref(place) => {
self.access_place(
location,
(place, span),
@@ -1243,7 +1258,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
- Rvalue::Len(place) | Rvalue::Discriminant(place) => {
+ &(Rvalue::Len(place) | Rvalue::Discriminant(place)) => {
let af = match *rvalue {
Rvalue::Len(..) => Some(ArtificialField::ArrayLength),
Rvalue::Discriminant(..) => None,
@@ -1264,8 +1279,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
);
}
- Rvalue::BinaryOp(_bin_op, box (ref operand1, ref operand2))
- | Rvalue::CheckedBinaryOp(_bin_op, box (ref operand1, ref operand2)) => {
+ Rvalue::BinaryOp(_bin_op, box (operand1, operand2))
+ | Rvalue::CheckedBinaryOp(_bin_op, box (operand1, operand2)) => {
self.consume_operand(location, (operand1, span), flow_state);
self.consume_operand(location, (operand2, span), flow_state);
}
@@ -1274,7 +1289,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// nullary ops take no dynamic input; no borrowck effect.
}
- Rvalue::Aggregate(ref aggregate_kind, ref operands) => {
+ Rvalue::Aggregate(aggregate_kind, operands) => {
// We need to report back the list of mutable upvars that were
// moved into the closure and subsequently used by the closure,
// in order to populate our used_mut set.
@@ -2246,6 +2261,7 @@ mod error {
use super::*;
pub struct BorrowckErrors<'tcx> {
+ tcx: TyCtxt<'tcx>,
/// This field keeps track of move errors that are to be reported for given move indices.
///
/// There are situations where many errors can be reported for a single move out (see #53807)
@@ -2268,19 +2284,24 @@ mod error {
tainted_by_errors: Option<ErrorGuaranteed>,
}
- impl BorrowckErrors<'_> {
- pub fn new() -> Self {
+ impl<'tcx> BorrowckErrors<'tcx> {
+ pub fn new(tcx: TyCtxt<'tcx>) -> Self {
BorrowckErrors {
+ tcx,
buffered_move_errors: BTreeMap::new(),
buffered: Default::default(),
tainted_by_errors: None,
}
}
- // FIXME(eddyb) this is a suboptimal API because `tainted_by_errors` is
- // set before any emission actually happens (weakening the guarantee).
pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) {
- self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+ if let None = self.tainted_by_errors {
+ self.tainted_by_errors = Some(
+ self.tcx
+ .sess
+ .delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"),
+ )
+ }
t.buffer(&mut self.buffered);
}
@@ -2288,8 +2309,8 @@ mod error {
t.buffer(&mut self.buffered);
}
- pub fn set_tainted_by_errors(&mut self) {
- self.tainted_by_errors = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
+ pub fn set_tainted_by_errors(&mut self, e: ErrorGuaranteed) {
+ self.tainted_by_errors = Some(e);
}
}
diff --git a/compiler/rustc_borrowck/src/location.rs b/compiler/rustc_borrowck/src/location.rs
index 877944d3d..9fa7e218b 100644
--- a/compiler/rustc_borrowck/src/location.rs
+++ b/compiler/rustc_borrowck/src/location.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_index::vec::{Idx, IndexVec};
use rustc_middle::mir::{BasicBlock, Body, Location};
diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index 43253a2aa..b5e00f471 100644
--- a/compiler/rustc_borrowck/src/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
@@ -9,6 +11,7 @@ use std::ops::Index;
/// Compactly stores a set of `R0 member of [R1...Rn]` constraints,
/// indexed by the region `R0`.
+#[derive(Debug)]
pub(crate) struct MemberConstraintSet<'tcx, R>
where
R: Copy + Eq,
@@ -29,6 +32,7 @@ where
}
/// Represents a `R0 member of [R1..Rn]` constraint
+#[derive(Debug)]
pub(crate) struct NllMemberConstraint<'tcx> {
next_constraint: Option<NllMemberConstraintIndex>,
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 08fdd28eb..e379e6470 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! The entry point of the NLL borrow checker.
use rustc_data_structures::vec_map::VecMap;
@@ -71,7 +73,7 @@ pub(crate) fn replace_regions_in_mir<'tcx>(
// Replace all remaining regions with fresh inference variables.
renumber::renumber_mir(infcx, body, promoted);
- dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(()));
+ dump_mir(infcx.tcx, false, "renumber", &0, body, |_, _| Ok(()));
universal_regions
}
@@ -242,7 +244,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
mut liveness_constraints,
outlives_constraints,
member_constraints,
- closure_bounds_mapping,
universe_causes,
type_tests,
} = constraints;
@@ -264,7 +265,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
universal_region_relations,
outlives_constraints,
member_constraints,
- closure_bounds_mapping,
universe_causes,
type_tests,
liveness_constraints,
@@ -303,7 +303,10 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
if !nll_errors.is_empty() {
// Suppress unhelpful extra errors in `infer_opaque_types`.
- infcx.set_tainted_by_errors();
+ infcx.set_tainted_by_errors(infcx.tcx.sess.delay_span_bug(
+ body.span,
+ "`compute_regions` tainted `infcx` with errors but did not emit any errors",
+ ));
}
let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values);
@@ -328,7 +331,7 @@ pub(super) fn dump_mir_results<'tcx>(
return;
}
- dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| {
+ dump_mir(infcx.tcx, false, "nll", &0, body, |pass_where, out| {
match pass_where {
// Before the CFG, dump out the values for each region variable.
PassWhere::BeforeCFG => {
@@ -355,15 +358,13 @@ pub(super) fn dump_mir_results<'tcx>(
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
- let mut file =
- create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?;
+ let mut file = create_dump_file(infcx.tcx, "regioncx.all.dot", false, "nll", &0, body)?;
regioncx.dump_graphviz_raw_constraints(&mut file)?;
};
// Also dump the inference graph constraints as a graphviz file.
let _: io::Result<()> = try {
- let mut file =
- create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?;
+ let mut file = create_dump_file(infcx.tcx, "regioncx.scc.dot", false, "nll", &0, body)?;
regioncx.dump_graphviz_scc_constraints(&mut file)?;
};
}
diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs
index b2c8dfc82..f8a99a269 100644
--- a/compiler/rustc_borrowck/src/path_utils.rs
+++ b/compiler/rustc_borrowck/src/path_utils.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::borrow_set::{BorrowData, BorrowSet, TwoPhaseActivation};
use crate::places_conflict;
use crate::AccessDepth;
diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs
index 93d202e49..9f6b1fdfc 100644
--- a/compiler/rustc_borrowck/src/place_ext.rs
+++ b/compiler/rustc_borrowck/src/place_ext.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::borrow_set::LocalsStateAtExit;
use rustc_hir as hir;
use rustc_middle::mir::ProjectionElem;
diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs
index 0e71efd6f..89ac0dfa4 100644
--- a/compiler/rustc_borrowck/src/places_conflict.rs
+++ b/compiler/rustc_borrowck/src/places_conflict.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::ArtificialField;
use crate::Overlap;
use crate::{AccessDepth, Deep, Shallow};
@@ -318,16 +320,10 @@ fn place_projection_conflict<'tcx>(
debug!("place_element_conflict: DISJOINT-OR-EQ-DEREF");
Overlap::EqualOrDisjoint
}
- (ProjectionElem::OpaqueCast(v1), ProjectionElem::OpaqueCast(v2)) => {
- if v1 == v2 {
- // same type - recur.
- debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
- Overlap::EqualOrDisjoint
- } else {
- // Different types. Disjoint!
- debug!("place_element_conflict: DISJOINT-OPAQUE");
- Overlap::Disjoint
- }
+ (ProjectionElem::OpaqueCast(_), ProjectionElem::OpaqueCast(_)) => {
+ // casts to other types may always conflict irrespective of the type being cast to.
+ debug!("place_element_conflict: DISJOINT-OR-EQ-OPAQUE");
+ Overlap::EqualOrDisjoint
}
(ProjectionElem::Field(f1, _), ProjectionElem::Field(f2, _)) => {
if f1 == f2 {
diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs
index 2b50cbac9..6f2813498 100644
--- a/compiler/rustc_borrowck/src/prefixes.rs
+++ b/compiler/rustc_borrowck/src/prefixes.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
//! place are formed by stripping away fields and derefs, except that
//! we stop when we reach the deref of a shared reference. [...] "
diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
index fe5193102..6524b594e 100644
--- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
+++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! As part of generating the regions, if you enable `-Zdump-mir=nll`,
//! we will generate an annotated copy of the MIR that includes the
//! state of region inference. This code handles emitting the region
@@ -74,8 +76,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let mut constraints: Vec<_> = self.constraints.outlives().iter().collect();
constraints.sort_by_key(|c| (c.sup, c.sub));
for constraint in &constraints {
- let OutlivesConstraint { sup, sub, locations, category, span, variance_info: _ } =
- constraint;
+ let OutlivesConstraint { sup, sub, locations, category, span, .. } = constraint;
let (name, arg) = match locations {
Locations::All(span) => {
("All", tcx.sess.source_map().span_to_embeddable_string(*span))
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index f31ccd74c..2e15586e0 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! This module provides linkage between RegionInferenceContext and
//! `rustc_graphviz` traits, specialized to attaching borrowck analysis
//! data to rendered labels.
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 8b63294fb..90e2b6b69 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -6,10 +6,9 @@ use rustc_data_structures::frozen::Frozen;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diagnostic;
-use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
+use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::CRATE_HIR_ID;
use rustc_index::vec::IndexVec;
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
use rustc_infer::infer::outlives::test_type_match;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
@@ -19,9 +18,7 @@ use rustc_middle::mir::{
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
-use rustc_middle::ty::{
- self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable,
-};
+use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, TypeVisitable};
use rustc_span::Span;
use crate::{
@@ -89,10 +86,6 @@ pub struct RegionInferenceContext<'tcx> {
/// `member_region_scc`.
member_constraints_applied: Vec<AppliedMemberConstraint>,
- /// Map closure bounds to a `Span` that should be used for error reporting.
- closure_bounds_mapping:
- FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
/// Map universe indexes to information on why we created it.
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
@@ -135,6 +128,7 @@ pub struct RegionInferenceContext<'tcx> {
/// adds a new lower bound to the SCC it is analyzing: so you wind up
/// with `'R: 'O` where `'R` is the pick-region and `'O` is the
/// minimal viable option.
+#[derive(Debug)]
pub(crate) struct AppliedMemberConstraint {
/// The SCC that was affected. (The "member region".)
///
@@ -221,8 +215,8 @@ pub struct TypeTest<'tcx> {
/// The region `'x` that the type must outlive.
pub lower_bound: RegionVid,
- /// Where did this constraint arise and why?
- pub locations: Locations,
+ /// The span to blame.
+ pub span: Span,
/// A test which, if met by the region `'x`, proves that this type
/// constraint is satisfied.
@@ -265,10 +259,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universal_region_relations: Frozen<UniversalRegionRelations<'tcx>>,
outlives_constraints: OutlivesConstraintSet<'tcx>,
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
- closure_bounds_mapping: FxHashMap<
- Location,
- FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>,
- >,
universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
type_tests: Vec<TypeTest<'tcx>>,
liveness_constraints: LivenessValues<RegionVid>,
@@ -310,7 +300,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
rev_scc_graph: None,
member_constraints,
member_constraints_applied: Vec::new(),
- closure_bounds_mapping,
universe_causes,
scc_universes,
scc_representatives,
@@ -882,13 +871,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
if deduplicate_errors.insert((
erased_generic_kind,
type_test.lower_bound,
- type_test.locations,
+ type_test.span,
)) {
debug!(
"check_type_test: reporting error for erased_generic_kind={:?}, \
lower_bound_region={:?}, \
- type_test.locations={:?}",
- erased_generic_kind, type_test.lower_bound, type_test.locations,
+ type_test.span={:?}",
+ erased_generic_kind, type_test.lower_bound, type_test.span,
);
errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() });
@@ -931,7 +920,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> bool {
let tcx = infcx.tcx;
- let TypeTest { generic_kind, lower_bound, locations, verify_bound: _ } = type_test;
+ let TypeTest { generic_kind, lower_bound, span: _, verify_bound: _ } = type_test;
let generic_ty = generic_kind.to_ty(tcx);
let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else {
@@ -959,7 +948,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
propagated_outlives_requirements.push(ClosureOutlivesRequirement {
subject,
outlived_free_region: static_r,
- blame_span: locations.span(body),
+ blame_span: type_test.span,
category: ConstraintCategory::Boring,
});
@@ -1011,7 +1000,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
let requirement = ClosureOutlivesRequirement {
subject,
outlived_free_region: upper_bound,
- blame_span: locations.span(body),
+ blame_span: type_test.span,
category: ConstraintCategory::Boring,
};
debug!("try_promote_type_test: pushing {:#?}", requirement);
@@ -1716,6 +1705,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
});
}
+ #[instrument(level = "debug", skip(self, infcx, errors_buffer))]
fn check_member_constraints(
&self,
infcx: &InferCtxt<'tcx>,
@@ -1723,22 +1713,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) {
let member_constraints = self.member_constraints.clone();
for m_c_i in member_constraints.all_indices() {
- debug!("check_member_constraint(m_c_i={:?})", m_c_i);
+ debug!(?m_c_i);
let m_c = &member_constraints[m_c_i];
let member_region_vid = m_c.member_region_vid;
debug!(
- "check_member_constraint: member_region_vid={:?} with value {}",
- member_region_vid,
- self.region_value_str(member_region_vid),
+ ?member_region_vid,
+ value = ?self.region_value_str(member_region_vid),
);
let choice_regions = member_constraints.choice_regions(m_c_i);
- debug!("check_member_constraint: choice_regions={:?}", choice_regions);
+ debug!(?choice_regions);
// Did the member region wind up equal to any of the option regions?
if let Some(o) =
choice_regions.iter().find(|&&o_r| self.eval_equal(o_r, m_c.member_region_vid))
{
- debug!("check_member_constraint: evaluated as equal to {:?}", o);
+ debug!("evaluated as equal to {:?}", o);
continue;
}
@@ -1804,18 +1793,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}
}
- pub(crate) fn retrieve_closure_constraint_info(
- &self,
- constraint: OutlivesConstraint<'tcx>,
- ) -> Option<(ConstraintCategory<'tcx>, Span)> {
- match constraint.locations {
- Locations::All(_) => None,
- Locations::Single(loc) => {
- self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)).copied()
- }
- }
- }
-
/// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
pub(crate) fn find_outlives_blame_span(
&self,
@@ -1921,6 +1898,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
span: p_c.definition_span,
category: ConstraintCategory::OpaqueType,
variance_info: ty::VarianceDiagInfo::default(),
+ from_closure: false,
};
handle_constraint(constraint);
}
@@ -2066,31 +2044,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Classify each of the constraints along the path.
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path
.iter()
- .map(|constraint| {
- let (category, span, from_closure, cause_code) =
- if constraint.category == ConstraintCategory::ClosureBounds {
- if let Some((category, span)) =
- self.retrieve_closure_constraint_info(*constraint)
- {
- (category, span, true, ObligationCauseCode::MiscObligation)
- } else {
- (
- constraint.category,
- constraint.span,
- false,
- ObligationCauseCode::MiscObligation,
- )
- }
- } else {
- (constraint.category, constraint.span, false, cause_code.clone())
- };
- BlameConstraint {
- category,
- from_closure,
- cause: ObligationCause::new(span, CRATE_HIR_ID, cause_code),
- variance_info: constraint.variance_info,
- outlives_constraint: *constraint,
- }
+ .map(|constraint| BlameConstraint {
+ category: constraint.category,
+ from_closure: constraint.from_closure,
+ cause: ObligationCause::new(constraint.span, CRATE_HIR_ID, cause_code.clone()),
+ variance_info: constraint.variance_info,
+ outlives_constraint: *constraint,
})
.collect();
debug!("categorized_path={:#?}", categorized_path);
@@ -2274,92 +2233,6 @@ impl<'tcx> RegionDefinition<'tcx> {
}
}
-pub trait ClosureRegionRequirementsExt<'tcx> {
- fn apply_requirements(
- &self,
- tcx: TyCtxt<'tcx>,
- closure_def_id: DefId,
- closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryOutlivesConstraint<'tcx>>;
-}
-
-impl<'tcx> ClosureRegionRequirementsExt<'tcx> for ClosureRegionRequirements<'tcx> {
- /// Given an instance T of the closure type, this method
- /// instantiates the "extra" requirements that we computed for the
- /// closure into the inference context. This has the effect of
- /// adding new outlives obligations to existing variables.
- ///
- /// As described on `ClosureRegionRequirements`, the extra
- /// requirements are expressed in terms of regionvids that index
- /// into the free regions that appear on the closure type. So, to
- /// do this, we first copy those regions out from the type T into
- /// a vector. Then we can just index into that vector to extract
- /// out the corresponding region from T and apply the
- /// requirements.
- fn apply_requirements(
- &self,
- tcx: TyCtxt<'tcx>,
- closure_def_id: DefId,
- closure_substs: SubstsRef<'tcx>,
- ) -> Vec<QueryOutlivesConstraint<'tcx>> {
- debug!(
- "apply_requirements(closure_def_id={:?}, closure_substs={:?})",
- closure_def_id, closure_substs
- );
-
- // Extract the values of the free regions in `closure_substs`
- // into a vector. These are the regions that we will be
- // relating to one another.
- let closure_mapping = &UniversalRegions::closure_mapping(
- tcx,
- closure_substs,
- self.num_external_vids,
- tcx.typeck_root_def_id(closure_def_id),
- );
- debug!("apply_requirements: closure_mapping={:?}", closure_mapping);
-
- // Create the predicates.
- self.outlives_requirements
- .iter()
- .map(|outlives_requirement| {
- let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
-
- match outlives_requirement.subject {
- ClosureOutlivesSubject::Region(region) => {
- let region = closure_mapping[region];
- debug!(
- "apply_requirements: region={:?} \
- outlived_region={:?} \
- outlives_requirement={:?}",
- region, outlived_region, outlives_requirement,
- );
- (
- ty::Binder::dummy(ty::OutlivesPredicate(
- region.into(),
- outlived_region,
- )),
- ConstraintCategory::BoringNoLocation,
- )
- }
-
- ClosureOutlivesSubject::Ty(ty) => {
- debug!(
- "apply_requirements: ty={:?} \
- outlived_region={:?} \
- outlives_requirement={:?}",
- ty, outlived_region, outlives_requirement,
- );
- (
- ty::Binder::dummy(ty::OutlivesPredicate(ty.into(), outlived_region)),
- ConstraintCategory::BoringNoLocation,
- )
- }
- }
- })
- .collect()
- }
-}
-
#[derive(Clone, Debug)]
pub struct BlameConstraint<'tcx> {
pub category: ConstraintCategory<'tcx>,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 465f353aa..516a08077 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,18 +1,16 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::vec_map::VecMap;
use rustc_hir::def_id::LocalDefId;
use rustc_hir::OpaqueTyOrigin;
use rustc_infer::infer::TyCtxtInferExt as _;
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
-use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
+use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
- self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
-};
+use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
-use rustc_trait_selection::traits::TraitEngineExt as _;
+use rustc_trait_selection::traits::ObligationCtxt;
use super::RegionInferenceContext;
@@ -63,17 +61,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
opaque_ty_decls: VecMap<OpaqueTypeKey<'tcx>, (OpaqueHiddenType<'tcx>, OpaqueTyOrigin)>,
) -> VecMap<LocalDefId, OpaqueHiddenType<'tcx>> {
let mut result: VecMap<LocalDefId, OpaqueHiddenType<'tcx>> = VecMap::new();
+
+ let member_constraints: FxHashMap<_, _> = self
+ .member_constraints
+ .all_indices()
+ .map(|ci| (self.member_constraints[ci].key, ci))
+ .collect();
+ debug!(?member_constraints);
+
for (opaque_type_key, (concrete_type, origin)) in opaque_ty_decls {
let substs = opaque_type_key.substs;
debug!(?concrete_type, ?substs);
let mut subst_regions = vec![self.universal_regions.fr_static];
- let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
- if let ty::RePlaceholder(..) = region.kind() {
- // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
- return region;
- }
- let vid = self.to_region_vid(region);
+
+ let to_universal_region = |vid, subst_regions: &mut Vec<_>| {
trace!(?vid);
let scc = self.constraint_sccs.scc(vid);
trace!(?scc);
@@ -94,10 +96,33 @@ impl<'tcx> RegionInferenceContext<'tcx> {
infcx.tcx.lifetimes.re_static
}
}
+ };
+
+ // Start by inserting universal regions from the member_constraint choice regions.
+ // This will ensure they get precedence when folding the regions in the concrete type.
+ if let Some(&ci) = member_constraints.get(&opaque_type_key) {
+ for &vid in self.member_constraints.choice_regions(ci) {
+ to_universal_region(vid, &mut subst_regions);
+ }
+ }
+ debug!(?subst_regions);
+
+ // Next, insert universal regions from substs, so we can translate regions that appear
+ // in them but are not subject to member constraints, for instance closure substs.
+ let universal_substs = infcx.tcx.fold_regions(substs, |region, _| {
+ if let ty::RePlaceholder(..) = region.kind() {
+ // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs.
+ return region;
+ }
+ let vid = self.to_region_vid(region);
+ to_universal_region(vid, &mut subst_regions)
});
+ debug!(?universal_substs);
+ debug!(?subst_regions);
- subst_regions.sort();
- subst_regions.dedup();
+ // Deduplicate the set of regions while keeping the chosen order.
+ let subst_regions = subst_regions.into_iter().collect::<FxIndexSet<_>>();
+ debug!(?subst_regions);
let universal_concrete_type =
infcx.tcx.fold_regions(concrete_type, |region, _| match *region {
@@ -108,8 +133,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.unwrap_or(infcx.tcx.lifetimes.re_erased),
_ => region,
});
-
- debug!(?universal_concrete_type, ?universal_substs);
+ debug!(?universal_concrete_type);
let opaque_type_key =
OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs };
@@ -221,12 +245,12 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
instantiated_ty: OpaqueHiddenType<'tcx>,
origin: OpaqueTyOrigin,
) -> Ty<'tcx> {
- if self.is_tainted_by_errors() {
- return self.tcx.ty_error();
+ if let Some(e) = self.tainted_by_errors() {
+ return self.tcx.ty_error_with_guaranteed(e);
}
let definition_ty = instantiated_ty
- .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false, origin)
+ .remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;
if !check_opaque_type_parameter_valid(
@@ -252,48 +276,45 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
// type-alias-impl-trait/issue-67844-nested-opaque.rs
let infcx =
self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
+ let ocx = ObligationCtxt::new(&infcx);
// Require the hidden type to be well-formed with only the generics of the opaque type.
// Defining use functions may have more bounds than the opaque type, which is ok, as long as the
// hidden type is well formed even without those bounds.
- let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()))
- .to_predicate(infcx.tcx);
- let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
+ let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into()));
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
// the bounds that the function supplies.
let opaque_ty = self.tcx.mk_opaque(def_id.to_def_id(), id_substs);
- match infcx
- .at(&ObligationCause::misc(instantiated_ty.span, body_id), param_env)
- .eq(opaque_ty, definition_ty)
- {
- Ok(infer_ok) => {
- for obligation in infer_ok.obligations {
- fulfillment_cx.register_predicate_obligation(&infcx, obligation);
- }
- }
- Err(err) => {
- infcx
- .err_ctxt()
- .report_mismatched_types(
- &ObligationCause::misc(instantiated_ty.span, body_id),
- opaque_ty,
- definition_ty,
- err,
- )
- .emit();
- }
+ if let Err(err) = ocx.eq(
+ &ObligationCause::misc(instantiated_ty.span, body_id),
+ param_env,
+ opaque_ty,
+ definition_ty,
+ ) {
+ infcx
+ .err_ctxt()
+ .report_mismatched_types(
+ &ObligationCause::misc(instantiated_ty.span, body_id),
+ opaque_ty,
+ definition_ty,
+ err,
+ )
+ .emit();
}
- fulfillment_cx.register_predicate_obligation(
- &infcx,
- Obligation::misc(instantiated_ty.span, body_id, param_env, predicate),
- );
+ ocx.register_obligation(Obligation::misc(
+ infcx.tcx,
+ instantiated_ty.span,
+ body_id,
+ param_env,
+ predicate,
+ ));
// Check that all obligations are satisfied by the implementation's
// version.
- let errors = fulfillment_cx.select_all_or_error(&infcx);
+ let errors = ocx.select_all_or_error();
// This is still required for many(half of the tests in ui/type-alias-impl-trait)
// tests to pass
@@ -302,8 +323,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
if errors.is_empty() {
definition_ty
} else {
- infcx.err_ctxt().report_fulfillment_errors(&errors, None, false);
- self.tcx.ty_error()
+ let reported = infcx.err_ctxt().report_fulfillment_errors(&errors, None);
+ self.tcx.ty_error_with_guaranteed(reported)
}
}
}
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index 1e6798eee..167f66460 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use crate::constraints::ConstraintSccIndex;
use crate::RegionInferenceContext;
use itertools::Itertools;
diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs
index de20a4bb4..7498ddccf 100644
--- a/compiler/rustc_borrowck/src/region_infer/values.rs
+++ b/compiler/rustc_borrowck/src/region_infer/values.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::fx::FxIndexSet;
use rustc_index::bit_set::SparseBitMatrix;
use rustc_index::interval::IntervalSet;
diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs
index f30237690..084754830 100644
--- a/compiler/rustc_borrowck/src/renumber.rs
+++ b/compiler/rustc_borrowck/src/renumber.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_index::vec::IndexVec;
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::mir::visit::{MutVisitor, TyContext};
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index cff3089c3..577332c07 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -49,7 +49,7 @@ pub(crate) struct GenericDoesNotLiveLongEnough {
#[derive(LintDiagnostic)]
#[diag(borrowck_var_does_not_need_mut)]
pub(crate) struct VarNeedNotMut {
- #[suggestion_short(applicability = "machine-applicable", code = "")]
+ #[suggestion(style = "short", applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(Diagnostic)]
@@ -148,3 +148,95 @@ pub(crate) enum RequireStaticErr {
multi_span: MultiSpan,
},
}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureVarPathUseCause {
+ #[label(borrowck_borrow_due_to_use_generator)]
+ BorrowInGenerator {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_use_due_to_use_generator)]
+ UseInGenerator {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_assign_due_to_use_generator)]
+ AssignInGenerator {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_assign_part_due_to_use_generator)]
+ AssignPartInGenerator {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_borrow_due_to_use_closure)]
+ BorrowInClosure {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_use_due_to_use_closure)]
+ UseInClosure {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_assign_due_to_use_closure)]
+ AssignInClosure {
+ #[primary_span]
+ path_span: Span,
+ },
+ #[label(borrowck_assign_part_due_to_use_closure)]
+ AssignPartInClosure {
+ #[primary_span]
+ path_span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureVarKind {
+ #[label(borrowck_capture_immute)]
+ Immute {
+ #[primary_span]
+ kind_span: Span,
+ },
+ #[label(borrowck_capture_mut)]
+ Mut {
+ #[primary_span]
+ kind_span: Span,
+ },
+ #[label(borrowck_capture_move)]
+ Move {
+ #[primary_span]
+ kind_span: Span,
+ },
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum CaptureVarCause {
+ #[label(borrowck_var_borrow_by_use_place_in_generator)]
+ BorrowUsePlaceGenerator {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+ #[label(borrowck_var_borrow_by_use_place_in_closure)]
+ BorrowUsePlaceClosure {
+ place: String,
+ #[primary_span]
+ var_span: Span,
+ },
+}
+
+#[derive(Diagnostic)]
+#[diag(borrowck_cannot_move_when_borrowed, code = "E0505")]
+pub(crate) struct MoveBorrow<'a> {
+ pub place: &'a str,
+ pub borrow_place: &'a str,
+ pub value_place: &'a str,
+ #[primary_span]
+ #[label(move_label)]
+ pub span: Span,
+ #[label]
+ pub borrow_span: Span,
+}
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index a581726a1..3617bf58b 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -88,12 +88,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
category: ConstraintCategory<'tcx>,
) {
self.prove_predicate(
- ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
+ ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate {
trait_ref,
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
- }))
- .to_predicate(self.tcx()),
+ }))),
locations,
category,
);
@@ -122,14 +121,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
pub(super) fn prove_predicates(
&mut self,
- predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
+ predicates: impl IntoIterator<Item = impl ToPredicate<'tcx> + std::fmt::Debug>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
for predicate in predicates {
- let predicate = predicate.to_predicate(self.tcx());
- debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
-
self.prove_predicate(predicate, locations, category);
}
}
@@ -137,11 +133,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(super) fn prove_predicate(
&mut self,
- predicate: ty::Predicate<'tcx>,
+ predicate: impl ToPredicate<'tcx> + std::fmt::Debug,
locations: Locations,
category: ConstraintCategory<'tcx>,
) {
let param_env = self.param_env;
+ let predicate = predicate.to_predicate(self.tcx());
self.fully_perform_op(
locations,
category,
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index d5bfc2f52..ce7f857e2 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -1,10 +1,10 @@
-use rustc_infer::infer::canonical::QueryOutlivesConstraint;
+use rustc_hir::def_id::DefId;
use rustc_infer::infer::canonical::QueryRegionConstraints;
use rustc_infer::infer::outlives::env::RegionBoundPairs;
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
-use rustc_middle::mir::ConstraintCategory;
+use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, TyCtxt};
@@ -38,6 +38,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
locations: Locations,
span: Span,
category: ConstraintCategory<'tcx>,
+ from_closure: bool,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
}
@@ -64,6 +65,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
span,
category,
constraints,
+ from_closure: false,
}
}
@@ -81,12 +83,62 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
}
self.constraints.member_constraints = tmp;
- for query_constraint in outlives {
- self.convert(query_constraint);
+ for (predicate, constraint_category) in outlives {
+ // At the moment, we never generate any "higher-ranked"
+ // region constraints like `for<'a> 'a: 'b`. At some point
+ // when we move to universes, we will, and this assertion
+ // will start to fail.
+ let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
+ bug!("query_constraint {:?} contained bound vars", predicate,);
+ });
+
+ self.convert(predicate, *constraint_category);
}
}
- fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
+ /// Given an instance of the closure type, this method instantiates the "extra" requirements
+ /// that we computed for the closure. This has the effect of adding new outlives obligations
+ /// to existing region variables in `closure_substs`.
+ #[instrument(skip(self), level = "debug")]
+ pub fn apply_closure_requirements(
+ &mut self,
+ closure_requirements: &ClosureRegionRequirements<'tcx>,
+ closure_def_id: DefId,
+ closure_substs: ty::SubstsRef<'tcx>,
+ ) {
+ // Extract the values of the free regions in `closure_substs`
+ // into a vector. These are the regions that we will be
+ // relating to one another.
+ let closure_mapping = &UniversalRegions::closure_mapping(
+ self.tcx,
+ closure_substs,
+ closure_requirements.num_external_vids,
+ closure_def_id.expect_local(),
+ );
+ debug!(?closure_mapping);
+
+ // Create the predicates.
+ let backup = (self.category, self.span, self.from_closure);
+ self.from_closure = true;
+ for outlives_requirement in &closure_requirements.outlives_requirements {
+ let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
+ let subject = match outlives_requirement.subject {
+ ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
+ ClosureOutlivesSubject::Ty(ty) => ty.into(),
+ };
+
+ self.category = outlives_requirement.category;
+ self.span = outlives_requirement.blame_span;
+ self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
+ }
+ (self.category, self.span, self.from_closure) = backup;
+ }
+
+ fn convert(
+ &mut self,
+ predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
+ constraint_category: ConstraintCategory<'tcx>,
+ ) {
debug!("generate: constraints at: {:#?}", self.locations);
// Extract out various useful fields we'll need below.
@@ -94,17 +146,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
tcx, region_bound_pairs, implicit_region_bound, param_env, ..
} = *self;
- // At the moment, we never generate any "higher-ranked"
- // region constraints like `for<'a> 'a: 'b`. At some point
- // when we move to universes, we will, and this assertion
- // will start to fail.
- let ty::OutlivesPredicate(k1, r2) =
- query_constraint.0.no_bound_vars().unwrap_or_else(|| {
- bug!("query_constraint {:?} contained bound vars", query_constraint,);
- });
-
- let constraint_category = query_constraint.1;
-
+ let ty::OutlivesPredicate(k1, r2) = predicate;
match k1.unpack() {
GenericArgKind::Lifetime(r1) => {
let r1_vid = self.to_region_vid(r1);
@@ -127,10 +169,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
.type_must_outlive(origin, t1, r2, constraint_category);
}
- GenericArgKind::Const(_) => {
- // Consts cannot outlive one another, so we
- // don't need to handle any relations here.
- }
+ GenericArgKind::Const(_) => unreachable!(),
}
}
@@ -160,7 +199,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
verify_bound: VerifyBound<'tcx>,
) -> TypeTest<'tcx> {
let lower_bound = self.to_region_vid(region);
- TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
+ TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
}
fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
@@ -188,6 +227,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
sub,
sup,
variance_info: ty::VarianceDiagInfo::default(),
+ from_closure: self.from_closure,
});
}
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 029095926..14cfc3613 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -247,12 +247,13 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
.and(type_op::normalize::Normalize::new(ty))
.fully_perform(self.infcx)
.unwrap_or_else(|_| {
- self.infcx
+ let reported = self
+ .infcx
.tcx
.sess
.delay_span_bug(span, &format!("failed to normalize {:?}", ty));
TypeOpOutput {
- output: self.infcx.tcx.ty_error(),
+ output: self.infcx.tcx.ty_error_with_guaranteed(reported),
constraints: None,
error_info: None,
}
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index a66ddd27d..62c6f9581 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -42,8 +42,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
user_provided_sig = None;
} else {
let typeck_results = self.tcx().typeck(mir_def_id);
- user_provided_sig = typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id()).map(
- |user_provided_poly_sig| {
+ user_provided_sig =
+ typeck_results.user_provided_sigs.get(&mir_def_id).map(|user_provided_poly_sig| {
// Instantiate the canonicalized variables from
// user-provided signature (e.g., the `_` in the code
// above) with fresh variables.
@@ -60,8 +60,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
LateBoundRegionConversionTime::FnCall,
poly_sig,
)
- },
- );
+ });
}
debug!(?normalized_input_tys, ?body.local_decls);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index bc76a465e..b344ab46a 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -121,8 +121,8 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
}
}
-// For every potentially drop()-touched region `region` in `local`'s type
-// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
+/// For every potentially drop()-touched region `region` in `local`'s type
+/// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact.
pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
typeck: &mut TypeChecker<'_, 'tcx>,
local: Local,
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3c1c3ab45..6d4ec6b72 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
//! This pass type-checks the MIR to ensure it is not broken.
use std::rc::Rc;
@@ -27,12 +29,11 @@ use rustc_middle::mir::AssertKind;
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::cast::CastTy;
-use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
+use rustc_middle::ty::subst::{SubstsRef, UserSubsts};
use rustc_middle::ty::visit::TypeVisitable;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
- OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType,
- UserTypeAnnotationIndex,
+ OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
};
use rustc_span::def_id::CRATE_DEF_ID;
use rustc_span::{Span, DUMMY_SP};
@@ -61,7 +62,7 @@ use crate::{
region_infer::values::{
LivenessValues, PlaceholderIndex, PlaceholderIndices, RegionValueElements,
},
- region_infer::{ClosureRegionRequirementsExt, TypeTest},
+ region_infer::TypeTest,
type_check::free_region_relations::{CreateResult, UniversalRegionRelations},
universal_regions::{DefiningTy, UniversalRegions},
Upvar,
@@ -144,7 +145,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
liveness_constraints: LivenessValues::new(elements.clone()),
outlives_constraints: OutlivesConstraintSet::default(),
member_constraints: MemberConstraintSet::default(),
- closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
universe_causes: FxHashMap::default(),
};
@@ -234,11 +234,11 @@ pub(crate) fn type_check<'mir, 'tcx>(
let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
if hidden_type.has_non_region_infer() {
- infcx.tcx.sess.delay_span_bug(
+ let reported = infcx.tcx.sess.delay_span_bug(
decl.hidden_type.span,
&format!("could not resolve {:#?}", hidden_type.ty.kind()),
);
- hidden_type.ty = infcx.tcx.ty_error();
+ hidden_type.ty = infcx.tcx.ty_error_with_guaranteed(reported);
}
(opaque_type_key, (hidden_type, decl.origin))
@@ -547,10 +547,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context {
let tcx = self.tcx();
- let trait_ref = ty::TraitRef {
- def_id: tcx.require_lang_item(LangItem::Copy, Some(self.last_span)),
- substs: tcx.mk_substs_trait(place_ty.ty, &[]),
- };
+ let trait_ref = tcx.at(self.last_span).mk_trait_ref(LangItem::Copy, [place_ty.ty]);
// To have a `Copy` operand, the type `T` of the
// value must be `Copy`. Note that we prove that `T: Copy`,
@@ -584,8 +581,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// modify their locations.
let all_facts = &mut None;
let mut constraints = Default::default();
- let mut type_tests = Default::default();
- let mut closure_bounds = Default::default();
let mut liveness_constraints =
LivenessValues::new(Rc::new(RegionValueElements::new(&promoted_body)));
// Don't try to add borrow_region facts for the promoted MIR
@@ -596,11 +591,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
&mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints,
);
- mem::swap(&mut this.cx.borrowck_context.constraints.type_tests, &mut type_tests);
- mem::swap(
- &mut this.cx.borrowck_context.constraints.closure_bounds_mapping,
- &mut closure_bounds,
- );
mem::swap(
&mut this.cx.borrowck_context.constraints.liveness_constraints,
&mut liveness_constraints,
@@ -621,13 +611,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
swap_constraints(self);
let locations = location.to_locations();
-
- // Use location of promoted const in collected constraints
- for type_test in type_tests.iter() {
- let mut type_test = type_test.clone();
- type_test.locations = locations;
- self.cx.borrowck_context.constraints.type_tests.push(type_test)
- }
for constraint in constraints.outlives().iter() {
let mut constraint = constraint.clone();
constraint.locations = locations;
@@ -653,18 +636,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
.add_element(region, location);
}
}
-
- if !closure_bounds.is_empty() {
- let combined_bounds_mapping =
- closure_bounds.into_iter().flat_map(|(_, value)| value).collect();
- let existing = self
- .cx
- .borrowck_context
- .constraints
- .closure_bounds_mapping
- .insert(location, combined_bounds_mapping);
- assert!(existing.is_none(), "Multiple promoteds/closures at the same location.");
- }
}
fn sanitize_projection(
@@ -941,9 +912,6 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
- pub(crate) closure_bounds_mapping:
- FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory<'tcx>, Span)>>,
-
pub(crate) universe_causes: FxHashMap<ty::UniverseIndex, UniverseInfo<'tcx>>,
pub(crate) type_tests: Vec<TypeTest<'tcx>>,
@@ -1097,8 +1065,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
self.prove_predicate(
- ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into()))
- .to_predicate(self.tcx()),
+ ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())),
Locations::All(span),
ConstraintCategory::TypeAnnotation,
);
@@ -1222,8 +1189,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
let tcx = self.tcx();
debug!("stmt kind: {:?}", stmt.kind);
- match stmt.kind {
- StatementKind::Assign(box (ref place, ref rv)) => {
+ match &stmt.kind {
+ StatementKind::Assign(box (place, rv)) => {
// Assignments to temporaries are not "interesting";
// they are not caused by the user, but rather artifacts
// of lowering. Assignments to other sorts of places *are* interesting
@@ -1303,10 +1270,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
self.check_rvalue(body, rv, location);
if !self.unsized_feature_enabled() {
- let trait_ref = ty::TraitRef {
- def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
- substs: tcx.mk_substs_trait(place_ty, &[]),
- };
+ let trait_ref =
+ tcx.at(self.last_span).mk_trait_ref(LangItem::Sized, [place_ty]);
self.prove_trait_ref(
trait_ref,
location.to_locations(),
@@ -1314,11 +1279,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
}
- StatementKind::AscribeUserType(box (ref place, ref projection), variance) => {
+ StatementKind::AscribeUserType(box (place, projection), variance) => {
let place_ty = place.ty(body, tcx).ty;
if let Err(terr) = self.relate_type_and_user_type(
place_ty,
- variance,
+ *variance,
projection,
Locations::All(stmt.source_info.span),
ConstraintCategory::TypeAnnotation,
@@ -1335,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
}
- StatementKind::Intrinsic(box ref kind) => match kind {
+ StatementKind::Intrinsic(box kind) => match kind {
NonDivergingIntrinsic::Assume(op) => self.check_operand(op, location),
NonDivergingIntrinsic::CopyNonOverlapping(..) => span_bug!(
stmt.source_info.span,
@@ -1363,7 +1328,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
) {
let tcx = self.tcx();
debug!("terminator kind: {:?}", term.kind);
- match term.kind {
+ match &term.kind {
TerminatorKind::Goto { .. }
| TerminatorKind::Resume
| TerminatorKind::Abort
@@ -1377,7 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// no checks needed for these
}
- TerminatorKind::DropAndReplace { ref place, ref value, target: _, unwind: _ } => {
+ TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
let place_ty = place.ty(body, tcx).ty;
let rv_ty = value.ty(body, tcx);
@@ -1395,13 +1360,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}
}
- TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
+ TerminatorKind::SwitchInt { discr, switch_ty, .. } => {
self.check_operand(discr, term_location);
let discr_ty = discr.ty(body, tcx);
if let Err(terr) = self.sub_types(
discr_ty,
- switch_ty,
+ *switch_ty,
term_location.to_locations(),
ConstraintCategory::Assignment,
) {
@@ -1419,14 +1384,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// FIXME: check the values
}
- TerminatorKind::Call {
- ref func,
- ref args,
- ref destination,
- from_hir_call,
- target,
- ..
- } => {
+ TerminatorKind::Call { func, args, destination, from_hir_call, target, .. } => {
self.check_operand(func, term_location);
for arg in args {
self.check_operand(arg, term_location);
@@ -1466,7 +1424,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ConstraintCategory::Boring,
);
let sig = self.normalize(sig, term_location);
- self.check_call_dest(body, term, &sig, *destination, target, term_location);
+ self.check_call_dest(body, term, &sig, *destination, *target, term_location);
// The ordinary liveness rules will ensure that all
// regions in the type of the callee are live here. We
@@ -1484,9 +1442,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.add_element(region_vid, term_location);
}
- self.check_call_inputs(body, term, &sig, args, term_location, from_hir_call);
+ self.check_call_inputs(body, term, &sig, args, term_location, *from_hir_call);
}
- TerminatorKind::Assert { ref cond, ref msg, .. } => {
+ TerminatorKind::Assert { cond, msg, .. } => {
self.check_operand(cond, term_location);
let cond_ty = cond.ty(body, tcx);
@@ -1494,7 +1452,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
}
- if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
+ if let AssertKind::BoundsCheck { len, index } = msg {
if len.ty(body, tcx) != tcx.types.usize {
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
}
@@ -1503,7 +1461,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
}
- TerminatorKind::Yield { ref value, .. } => {
+ TerminatorKind::Yield { value, .. } => {
self.check_operand(value, term_location);
let value_ty = value.ty(body, tcx);
@@ -1594,10 +1552,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
}
None => {
- if !self
- .tcx()
- .conservative_is_privately_uninhabited(self.param_env.and(sig.output()))
- {
+ if !sig.output().is_privately_uninhabited(self.tcx(), self.param_env) {
span_mirbug!(self, term, "call to converging function {:?} w/o dest", sig);
}
}
@@ -1873,6 +1828,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
#[instrument(skip(self, body), level = "debug")]
fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
let tcx = self.tcx();
+ let span = body.source_info(location).span;
match rvalue {
Rvalue::Aggregate(ak, ops) => {
@@ -1896,12 +1852,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
Operand::Move(place) => {
// Make sure that repeated elements implement `Copy`.
- let span = body.source_info(location).span;
let ty = place.ty(body, tcx).ty;
- let trait_ref = ty::TraitRef::new(
- tcx.require_lang_item(LangItem::Copy, Some(span)),
- tcx.mk_substs_trait(ty, &[]),
- );
+ let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Copy, [ty]);
self.prove_trait_ref(
trait_ref,
@@ -1914,10 +1866,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
&Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
- let trait_ref = ty::TraitRef {
- def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
- substs: tcx.mk_substs_trait(ty, &[]),
- };
+ let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, [ty]);
self.prove_trait_ref(
trait_ref,
@@ -1929,10 +1878,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Rvalue::ShallowInitBox(operand, ty) => {
self.check_operand(operand, location);
- let trait_ref = ty::TraitRef {
- def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
- substs: tcx.mk_substs_trait(*ty, &[]),
- };
+ let trait_ref = tcx.at(span).mk_trait_ref(LangItem::Sized, [*ty]);
self.prove_trait_ref(
trait_ref,
@@ -2029,11 +1975,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
CastKind::Pointer(PointerCast::Unsize) => {
let &ty = ty;
- let trait_ref = ty::TraitRef {
- def_id: tcx
- .require_lang_item(LangItem::CoerceUnsized, Some(self.last_span)),
- substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]),
- };
+ let trait_ref = tcx
+ .at(span)
+ .mk_trait_ref(LangItem::CoerceUnsized, [op.ty(body, tcx), ty]);
self.prove_trait_ref(
trait_ref,
@@ -2062,8 +2006,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
let outlives_predicate =
- tcx.mk_predicate(Binder::dummy(ty::PredicateKind::TypeOutlives(
- ty::OutlivesPredicate(self_ty, *region),
+ tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(
+ ty::Clause::TypeOutlives(ty::OutlivesPredicate(self_ty, *region)),
)));
self.prove_predicate(
outlives_predicate,
@@ -2562,6 +2506,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
span: location.to_locations().span(body),
category,
variance_info: ty::VarianceDiagInfo::default(),
+ from_closure: false,
});
match mutbl {
@@ -2636,7 +2581,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
// For closures, we have some **extra requirements** we
- //
// have to check. In particular, in their upvars and
// signatures, closures often reference various regions
// from the surrounding function -- we call those the
@@ -2679,62 +2623,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
substs: SubstsRef<'tcx>,
location: Location,
) -> ty::InstantiatedPredicates<'tcx> {
- if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements
- {
- let closure_constraints = QueryRegionConstraints {
- outlives: closure_region_requirements.apply_requirements(
- tcx,
- def_id.to_def_id(),
- substs,
- ),
-
- // Presently, closures never propagate member
- // constraints to their parents -- they are enforced
- // locally. This is largely a non-issue as member
- // constraints only come from `-> impl Trait` and
- // friends which don't appear (thus far...) in
- // closures.
- member_constraints: vec![],
- };
-
- let bounds_mapping = closure_constraints
- .outlives
- .iter()
- .enumerate()
- .filter_map(|(idx, constraint)| {
- let ty::OutlivesPredicate(k1, r2) =
- constraint.0.no_bound_vars().unwrap_or_else(|| {
- bug!("query_constraint {:?} contained bound vars", constraint,);
- });
-
- match k1.unpack() {
- GenericArgKind::Lifetime(r1) => {
- // constraint is r1: r2
- let r1_vid = self.borrowck_context.universal_regions.to_region_vid(r1);
- let r2_vid = self.borrowck_context.universal_regions.to_region_vid(r2);
- let outlives_requirements =
- &closure_region_requirements.outlives_requirements[idx];
- Some((
- (r1_vid, r2_vid),
- (outlives_requirements.category, outlives_requirements.blame_span),
- ))
- }
- GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
- }
- })
- .collect();
-
- let existing = self
- .borrowck_context
- .constraints
- .closure_bounds_mapping
- .insert(location, bounds_mapping);
- assert!(existing.is_none(), "Multiple closures at the same location.");
-
- self.push_region_constraints(
+ if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
+ constraint_conversion::ConstraintConversion::new(
+ self.infcx,
+ self.borrowck_context.universal_regions,
+ self.region_bound_pairs,
+ self.implicit_region_bound,
+ self.param_env,
location.to_locations(),
- ConstraintCategory::ClosureBounds,
- &closure_constraints,
+ DUMMY_SP, // irrelevant; will be overrided.
+ ConstraintCategory::Boring, // same as above.
+ &mut self.borrowck_context.constraints,
+ )
+ .apply_closure_requirements(
+ &closure_requirements,
+ def_id.to_def_id(),
+ substs,
);
}
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 4f2dc263b..b2702eafd 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -2,9 +2,8 @@ use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRe
use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_infer::traits::PredicateObligations;
use rustc_middle::mir::ConstraintCategory;
-use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::TypeRelation;
-use rustc_middle::ty::{self, Const, Ty};
+use rustc_middle::ty::{self, Ty};
use rustc_span::Span;
use rustc_trait_selection::traits::query::Fallible;
@@ -136,17 +135,11 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
span: self.locations.span(self.type_checker.body),
category: self.category,
variance_info: info,
+ from_closure: false,
},
);
}
- // We don't have to worry about the equality of consts during borrow checking
- // as consts always have a static lifetime.
- // FIXME(oli-obk): is this really true? We can at least have HKL and with
- // inline consts we may have further lifetimes that may be unsound to treat as
- // 'static.
- fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {}
-
fn normalization() -> NormalizationStrategy {
NormalizationStrategy::Eager
}
@@ -155,10 +148,7 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
true
}
- fn register_opaque_type_obligations(
- &mut self,
- obligations: PredicateObligations<'tcx>,
- ) -> Result<(), TypeError<'tcx>> {
+ fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
self.type_checker
.fully_perform_op(
self.locations,
@@ -171,6 +161,5 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
},
)
.unwrap();
- Ok(())
}
}
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 2beb5e0ab..a4a0c5b90 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -22,7 +22,9 @@ use rustc_hir::{BodyOwnerKind, HirId};
use rustc_index::vec::{Idx, IndexVec};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin};
use rustc_middle::ty::fold::TypeFoldable;
-use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt};
+use rustc_middle::ty::{
+ self, DefIdTree, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt,
+};
use rustc_middle::ty::{InternalSubsts, SubstsRef};
use std::iter;
@@ -241,7 +243,7 @@ impl<'tcx> UniversalRegions<'tcx> {
tcx: TyCtxt<'tcx>,
closure_substs: SubstsRef<'tcx>,
expected_num_vars: usize,
- typeck_root_def_id: DefId,
+ closure_def_id: LocalDefId,
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
region_mapping.push(tcx.lifetimes.re_static);
@@ -249,7 +251,7 @@ impl<'tcx> UniversalRegions<'tcx> {
region_mapping.push(fr);
});
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
+ for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
region_mapping.push(r);
});
@@ -339,9 +341,8 @@ impl<'tcx> UniversalRegions<'tcx> {
// tests, and the resulting print-outs include def-ids
// and other things that are not stable across tests!
// So we just include the region-vid. Annoying.
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
- err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
+ for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
+ err.note(&format!("late-bound region is {:?}", self.to_region_vid(r)));
});
}
DefiningTy::Generator(def_id, substs, _) => {
@@ -354,9 +355,8 @@ impl<'tcx> UniversalRegions<'tcx> {
// FIXME: As above, we'd like to print out the region
// `r` but doing so is not stable across architectures
// and so forth.
- let typeck_root_def_id = tcx.typeck_root_def_id(def_id);
- for_each_late_bound_region_defined_on(tcx, typeck_root_def_id, |r| {
- err.note(&format!("late-bound region is {:?}", self.to_region_vid(r),));
+ for_each_late_bound_region_in_recursive_scope(tcx, def_id.expect_local(), |r| {
+ err.note(&format!("late-bound region is {:?}", self.to_region_vid(r)));
});
}
DefiningTy::FnDef(def_id, substs) => {
@@ -421,13 +421,24 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
first_extern_index
} else {
// If this is a closure, generator, or inline-const, then the late-bound regions from the enclosing
- // function are actually external regions to us. For example, here, 'a is not local
+ // function/closures are actually external regions to us. For example, here, 'a is not local
// to the closure c (although it is local to the fn foo):
// fn foo<'a>() {
// let c = || { let x: &'a u32 = ...; }
// }
- self.infcx
- .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
+ for_each_late_bound_region_in_recursive_scope(
+ self.infcx.tcx,
+ self.infcx.tcx.local_parent(self.mir_def.did),
+ |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.infcx.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ },
+ );
+
// Any regions created during the execution of `defining_ty` or during the above
// late-bound region replacement are all considered 'extern' regions
self.infcx.num_region_vars()
@@ -444,12 +455,16 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
bound_inputs_and_output,
&mut indices,
);
- // Converse of above, if this is a function then the late-bound regions declared on its
- // signature are local to the fn.
- if self.mir_def.did.to_def_id() == typeck_root_def_id {
- self.infcx
- .replace_late_bound_regions_with_nll_infer_vars(self.mir_def.did, &mut indices);
- }
+ // Converse of above, if this is a function/closure then the late-bound regions declared on its
+ // signature are local.
+ for_each_late_bound_region_in_item(self.infcx.tcx, self.mir_def.did, |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.infcx.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ });
let (unnormalized_output_ty, mut unnormalized_input_tys) =
inputs_and_output.split_last().unwrap();
@@ -572,9 +587,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.did.to_def_id());
let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
let fr_substs = match defining_ty {
- DefiningTy::Closure(_, ref substs)
- | DefiningTy::Generator(_, ref substs, _)
- | DefiningTy::InlineConst(_, ref substs) => {
+ DefiningTy::Closure(_, substs)
+ | DefiningTy::Generator(_, substs, _)
+ | DefiningTy::InlineConst(_, substs) => {
// In the case of closures, we rely on the fact that
// the first N elements in the ClosureSubsts are
// inherited from the `typeck_root_def_id`.
@@ -692,7 +707,13 @@ trait InferCtxtExt<'tcx> {
where
T: TypeFoldable<'tcx>;
- fn replace_late_bound_regions_with_nll_infer_vars(
+ fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
+ &self,
+ mir_def_id: LocalDefId,
+ indices: &mut UniversalRegionIndices<'tcx>,
+ );
+
+ fn replace_late_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
@@ -746,13 +767,28 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
/// set of late-bound regions and checks for any that we have not yet seen, adding them to the
/// inputs vector.
#[instrument(skip(self, indices))]
- fn replace_late_bound_regions_with_nll_infer_vars(
+ fn replace_late_bound_regions_with_nll_infer_vars_in_recursive_scope(
+ &self,
+ mir_def_id: LocalDefId,
+ indices: &mut UniversalRegionIndices<'tcx>,
+ ) {
+ for_each_late_bound_region_in_recursive_scope(self.tcx, mir_def_id, |r| {
+ debug!(?r);
+ if !indices.indices.contains_key(&r) {
+ let region_vid = self.next_nll_region_var(FR);
+ debug!(?region_vid);
+ indices.insert_late_bound_region(r, region_vid.to_region_vid());
+ }
+ });
+ }
+
+ #[instrument(skip(self, indices))]
+ fn replace_late_bound_regions_with_nll_infer_vars_in_item(
&self,
mir_def_id: LocalDefId,
indices: &mut UniversalRegionIndices<'tcx>,
) {
- let typeck_root_def_id = self.tcx.typeck_root_def_id(mir_def_id.to_def_id());
- for_each_late_bound_region_defined_on(self.tcx, typeck_root_def_id, |r| {
+ for_each_late_bound_region_in_item(self.tcx, mir_def_id, |r| {
debug!(?r);
if !indices.indices.contains_key(&r) {
let region_vid = self.next_nll_region_var(FR);
@@ -803,21 +839,44 @@ impl<'tcx> UniversalRegionIndices<'tcx> {
}
}
-/// Iterates over the late-bound regions defined on fn_def_id and
-/// invokes `f` with the liberated form of each one.
-fn for_each_late_bound_region_defined_on<'tcx>(
+/// Iterates over the late-bound regions defined on `mir_def_id` and all of its
+/// parents, up to the typeck root, and invokes `f` with the liberated form
+/// of each one.
+fn for_each_late_bound_region_in_recursive_scope<'tcx>(
tcx: TyCtxt<'tcx>,
- fn_def_id: DefId,
+ mut mir_def_id: LocalDefId,
mut f: impl FnMut(ty::Region<'tcx>),
) {
- if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) {
- for &region_def_id in late_bounds.iter() {
- let name = tcx.item_name(region_def_id.to_def_id());
- let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion {
- scope: fn_def_id,
- bound_region: ty::BoundRegionKind::BrNamed(region_def_id.to_def_id(), name),
- }));
- f(liberated_region);
+ let typeck_root_def_id = tcx.typeck_root_def_id(mir_def_id.to_def_id());
+
+ // Walk up the tree, collecting late-bound regions until we hit the typeck root
+ loop {
+ for_each_late_bound_region_in_item(tcx, mir_def_id, &mut f);
+
+ if mir_def_id.to_def_id() == typeck_root_def_id {
+ break;
+ } else {
+ mir_def_id = tcx.local_parent(mir_def_id);
}
}
}
+
+/// Iterates over the late-bound regions defined on `mir_def_id` and all of its
+/// parents, up to the typeck root, and invokes `f` with the liberated form
+/// of each one.
+fn for_each_late_bound_region_in_item<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ mir_def_id: LocalDefId,
+ mut f: impl FnMut(ty::Region<'tcx>),
+) {
+ if !tcx.def_kind(mir_def_id).is_fn_like() {
+ return;
+ }
+
+ for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) {
+ let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; };
+ let liberated_region = tcx
+ .mk_region(ty::ReFree(ty::FreeRegion { scope: mir_def_id.to_def_id(), bound_region }));
+ f(liberated_region);
+ }
+}
diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index 8833753b1..e297b1230 100644
--- a/compiler/rustc_borrowck/src/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{