Merge BorrowCheckContext into TypeChecker.

Because there is no real reason for it to be a separate struct.
- It has no methods.
- It's easy to confuse with the nearby `BorrowckInferContext` (which
  does have methods).
- The `mut` ref to it in `TypeChecker` makes it seem like any of the
  fields within might be mutable, but only two (`all_facts` and
  `constraints`) actually are.
- Two of the fields are `pub(crate)` but can be private.

This change makes a lot of code more concise and readable.
This commit is contained in:
Nicholas Nethercote 2024-10-10 14:02:28 +11:00
parent f86c76a782
commit 6ecf80e1ad
7 changed files with 88 additions and 173 deletions

View File

@ -62,7 +62,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
{
let universe_info = error_info.to_universe_info(old_universe);
for u in (old_universe + 1)..=universe {
self.borrowck_context.constraints.universe_causes.insert(u, universe_info.clone());
self.constraints.universe_causes.insert(u, universe_info.clone());
}
}

View File

@ -48,9 +48,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// FIXME(async_closures): It's kind of wacky that we must apply this
// transformation here, since we do the same thing in HIR typeck.
// Maybe we could just fix up the canonicalized signature during HIR typeck?
if let DefiningTy::CoroutineClosure(_, args) =
self.borrowck_context.universal_regions.defining_ty
{
if let DefiningTy::CoroutineClosure(_, args) = self.universal_regions.defining_ty {
assert_matches!(
self.tcx().coroutine_kind(self.tcx().coroutine_for_closure(mir_def_id)),
Some(hir::CoroutineKind::Desugared(

View File

@ -39,8 +39,8 @@ pub(super) fn generate<'a, 'tcx>(
let free_regions = regions_that_outlive_free_regions(
typeck.infcx.num_region_vars(),
typeck.borrowck_context.universal_regions,
&typeck.borrowck_context.constraints.outlives_constraints,
typeck.universal_regions,
&typeck.constraints.outlives_constraints,
);
let (relevant_live_locals, boring_locals) =
compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
@ -59,11 +59,7 @@ pub(super) fn generate<'a, 'tcx>(
// Mark regions that should be live where they appear within rvalues or within a call: like
// args, regions, and types.
record_regular_live_regions(
typeck.tcx(),
&mut typeck.borrowck_context.constraints.liveness_constraints,
body,
);
record_regular_live_regions(typeck.tcx(), &mut typeck.constraints.liveness_constraints, body);
}
// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`

View File

@ -88,9 +88,9 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
body: &Body<'tcx>,
move_data: &MoveData<'tcx>,
) {
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
if let Some(facts) = typeck.all_facts.as_mut() {
debug!("populate_access_facts()");
let location_table = typeck.borrowck_context.location_table;
let location_table = typeck.location_table;
let mut extractor = UseFactsExtractor {
var_defined_at: &mut facts.var_defined_at,
@ -108,7 +108,7 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
local, local_decl.ty
);
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
let universal_regions = &typeck.borrowck_context.universal_regions;
let universal_regions = &typeck.universal_regions;
typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| {
let region_vid = universal_regions.to_region_vid(region);
facts.use_of_var_derefs_origin.push((local, region_vid.into()));
@ -125,9 +125,9 @@ pub(super) fn add_drop_of_var_derefs_origin<'tcx>(
kind: &GenericArg<'tcx>,
) {
debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind);
if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
if let Some(facts) = typeck.all_facts.as_mut() {
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
let universal_regions = &typeck.borrowck_context.universal_regions;
let universal_regions = &typeck.universal_regions;
typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| {
let region_vid = universal_regions.to_region_vid(drop_live_region);
facts.drop_of_var_derefs_origin.push((local, region_vid.into()));

View File

@ -47,13 +47,12 @@ pub(super) fn trace<'a, 'tcx>(
// When using `-Zpolonius=next`, compute the set of loans that can reach a given region.
if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
let borrowck_context = &mut typeck.borrowck_context;
let borrow_set = &borrowck_context.borrow_set;
let borrow_set = &typeck.borrow_set;
let mut live_loans = LiveLoans::new(borrow_set.len());
let outlives_constraints = &borrowck_context.constraints.outlives_constraints;
let outlives_constraints = &typeck.constraints.outlives_constraints;
let graph = outlives_constraints.graph(typeck.infcx.num_region_vars());
let region_graph =
graph.region_graph(outlives_constraints, borrowck_context.universal_regions.fr_static);
graph.region_graph(outlives_constraints, typeck.universal_regions.fr_static);
// Traverse each issuing region's constraints, and record the loan as flowing into the
// outlived region.
@ -73,7 +72,7 @@ pub(super) fn trace<'a, 'tcx>(
// Store the inflowing loans in the liveness constraints: they will be used to compute live
// loans when liveness data is recorded there.
borrowck_context.constraints.liveness_constraints.loans = Some(live_loans);
typeck.constraints.liveness_constraints.loans = Some(live_loans);
};
let cx = LivenessContext {
@ -222,7 +221,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
// It may be necessary to just pick out the parts of
// `add_drop_live_facts_for()` that make sense.
let facts_to_add: Vec<_> = {
let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at;
let drop_used = &self.cx.typeck.all_facts.as_ref()?.var_dropped_at;
let relevant_live_locals: FxIndexSet<_> =
relevant_live_locals.iter().copied().collect();
@ -235,12 +234,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
return None;
}
let location = match self
.cx
.typeck
.borrowck_context
.location_table
.to_location(*location_index)
let location = match self.cx.typeck.location_table.to_location(*location_index)
{
RichLocation::Start(l) => l,
RichLocation::Mid(l) => l,
@ -616,13 +610,9 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
tcx: typeck.tcx(),
param_env: typeck.param_env,
op: |r| {
let live_region_vid = typeck.borrowck_context.universal_regions.to_region_vid(r);
let live_region_vid = typeck.universal_regions.to_region_vid(r);
typeck
.borrowck_context
.constraints
.liveness_constraints
.add_points(live_region_vid, live_at);
typeck.constraints.liveness_constraints.add_points(live_region_vid, live_at);
},
});
}

View File

@ -156,25 +156,24 @@ pub(crate) fn type_check<'a, 'tcx>(
debug!(?normalized_inputs_and_output);
let mut borrowck_context = BorrowCheckContext {
let mut checker = TypeChecker {
infcx,
param_env,
last_span: body.span,
body,
user_type_annotations: &body.user_type_annotations,
region_bound_pairs: &region_bound_pairs,
known_type_outlives_obligations,
implicit_region_bound,
reported_errors: Default::default(),
universal_regions: &universal_regions,
location_table,
borrow_set,
all_facts,
borrow_set,
constraints: &mut constraints,
upvars,
};
let mut checker = TypeChecker::new(
infcx,
body,
param_env,
&region_bound_pairs,
known_type_outlives_obligations,
implicit_region_bound,
&mut borrowck_context,
);
checker.check_user_type_annotations();
let mut verifier = TypeVerifier::new(&mut checker, promoted);
@ -221,13 +220,12 @@ pub(crate) fn type_check<'a, 'tcx>(
infcx.tcx.fold_regions((opaque_type_key, hidden_type), |region, _| {
match region.kind() {
ty::ReVar(_) => region,
ty::RePlaceholder(placeholder) => checker
.borrowck_context
.constraints
.placeholder_region(infcx, placeholder),
ty::RePlaceholder(placeholder) => {
checker.constraints.placeholder_region(infcx, placeholder)
}
_ => ty::Region::new_var(
infcx.tcx,
checker.borrowck_context.universal_regions.to_region_vid(region),
checker.universal_regions.to_region_vid(region),
),
}
});
@ -240,25 +238,26 @@ pub(crate) fn type_check<'a, 'tcx>(
}
fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
let cx = &mut typeck.borrowck_context;
if let Some(facts) = cx.all_facts {
if let Some(facts) = typeck.all_facts {
let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation");
let location_table = cx.location_table;
facts.subset_base.extend(cx.constraints.outlives_constraints.outlives().iter().flat_map(
|constraint: &OutlivesConstraint<'_>| {
if let Some(from_location) = constraint.locations.from_location() {
Either::Left(iter::once((
constraint.sup.into(),
constraint.sub.into(),
location_table.mid_index(from_location),
)))
} else {
Either::Right(location_table.all_points().map(move |location| {
(constraint.sup.into(), constraint.sub.into(), location)
}))
}
},
));
let location_table = typeck.location_table;
facts.subset_base.extend(
typeck.constraints.outlives_constraints.outlives().iter().flat_map(
|constraint: &OutlivesConstraint<'_>| {
if let Some(from_location) = constraint.locations.from_location() {
Either::Left(iter::once((
constraint.sup.into(),
constraint.sub.into(),
location_table.mid_index(from_location),
)))
} else {
Either::Right(location_table.all_points().map(move |location| {
(constraint.sup.into(), constraint.sub.into(), location)
}))
}
},
),
);
}
}
@ -303,13 +302,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
let ty = self.sanitize_type(constant, constant.const_.ty());
self.cx.infcx.tcx.for_each_free_region(&ty, |live_region| {
let live_region_vid =
self.cx.borrowck_context.universal_regions.to_region_vid(live_region);
self.cx
.borrowck_context
.constraints
.liveness_constraints
.add_location(live_region_vid, location);
let live_region_vid = self.cx.universal_regions.to_region_vid(live_region);
self.cx.constraints.liveness_constraints.add_location(live_region_vid, location);
});
// HACK(compiler-errors): Constants that are gathered into Body.required_consts
@ -561,15 +555,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// Don't try to add borrow_region facts for the promoted MIR
let mut swap_constraints = |this: &mut Self| {
mem::swap(this.cx.borrowck_context.all_facts, all_facts);
mem::swap(
&mut this.cx.borrowck_context.constraints.outlives_constraints,
&mut constraints,
);
mem::swap(
&mut this.cx.borrowck_context.constraints.liveness_constraints,
&mut liveness_constraints,
);
mem::swap(this.cx.all_facts, all_facts);
mem::swap(&mut this.cx.constraints.outlives_constraints, &mut constraints);
mem::swap(&mut this.cx.constraints.liveness_constraints, &mut liveness_constraints);
};
swap_constraints(self);
@ -594,7 +582,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// temporary from the user's point of view.
constraint.category = ConstraintCategory::Boring;
}
self.cx.borrowck_context.constraints.outlives_constraints.push(constraint)
self.cx.constraints.outlives_constraints.push(constraint)
}
// If the region is live at least one location in the promoted MIR,
// then add a liveness constraint to the main MIR for this region
@ -604,11 +592,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
// unordered.
#[allow(rustc::potential_query_instability)]
for region in liveness_constraints.live_regions_unordered() {
self.cx
.borrowck_context
.constraints
.liveness_constraints
.add_location(region, location);
self.cx.constraints.liveness_constraints.add_location(region, location);
}
}
@ -863,15 +847,11 @@ struct TypeChecker<'a, 'tcx> {
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
}
struct BorrowCheckContext<'a, 'tcx> {
pub(crate) universal_regions: &'a UniversalRegions<'tcx>,
universal_regions: &'a UniversalRegions<'tcx>,
location_table: &'a LocationTable,
all_facts: &'a mut Option<AllFacts>,
borrow_set: &'a BorrowSet<'tcx>,
pub(crate) constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
upvars: &'a [&'a ty::CapturedPlace<'tcx>],
}
@ -1006,29 +986,6 @@ impl Locations {
}
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn new(
infcx: &'a BorrowckInferCtxt<'tcx>,
body: &'a Body<'tcx>,
param_env: ty::ParamEnv<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
implicit_region_bound: ty::Region<'tcx>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
) -> Self {
Self {
infcx,
last_span: body.span,
body,
user_type_annotations: &body.user_type_annotations,
param_env,
region_bound_pairs,
known_type_outlives_obligations,
implicit_region_bound,
borrowck_context,
reported_errors: Default::default(),
}
}
fn body(&self) -> &Body<'tcx> {
self.body
}
@ -1067,7 +1024,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
constraint_conversion::ConstraintConversion::new(
self.infcx,
self.borrowck_context.universal_regions,
self.universal_regions,
self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
@ -1075,7 +1032,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations,
locations.span(self.body),
category,
self.borrowck_context.constraints,
self.constraints,
)
.convert_all(data);
}
@ -1191,7 +1148,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// though.
let category = match place.as_local() {
Some(RETURN_PLACE) => {
let defining_ty = &self.borrowck_context.universal_regions.defining_ty;
let defining_ty = &self.universal_regions.defining_ty;
if defining_ty.is_const() {
if tcx.is_static(defining_ty.def_id()) {
ConstraintCategory::UseAsStatic
@ -1439,12 +1396,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// output) types in the signature must be live, since
// all the inputs that fed into it were live.
for &late_bound_region in map.values() {
let region_vid =
self.borrowck_context.universal_regions.to_region_vid(late_bound_region);
self.borrowck_context
.constraints
.liveness_constraints
.add_location(region_vid, term_location);
let region_vid = self.universal_regions.to_region_vid(late_bound_region);
self.constraints.liveness_constraints.add_location(region_vid, term_location);
}
self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
@ -1532,18 +1485,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
let dest_ty = self.normalize(dest_ty, term_location);
let category = match destination.as_local() {
Some(RETURN_PLACE) => {
if let BorrowCheckContext {
universal_regions:
UniversalRegions {
defining_ty:
DefiningTy::Const(def_id, _)
| DefiningTy::InlineConst(def_id, _),
..
},
..
} = self.borrowck_context
if let DefiningTy::Const(def_id, _) | DefiningTy::InlineConst(def_id, _) =
self.universal_regions.defining_ty
{
if tcx.is_static(*def_id) {
if tcx.is_static(def_id) {
ConstraintCategory::UseAsStatic
} else {
ConstraintCategory::UseAsConst
@ -2654,8 +2599,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
borrowed_place: &Place<'tcx>,
) {
// These constraints are only meaningful during borrowck:
let BorrowCheckContext { borrow_set, location_table, all_facts, constraints, .. } =
self.borrowck_context;
let Self { borrow_set, location_table, all_facts, constraints, .. } = self;
// In Polonius mode, we also push a `loan_issued_at` fact
// linking the loan to the region (in some cases, though,
@ -2685,12 +2629,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
let tcx = self.infcx.tcx;
let field = path_utils::is_upvar_field_projection(
tcx,
self.borrowck_context.upvars,
borrowed_place.as_ref(),
body,
);
let field =
path_utils::is_upvar_field_projection(tcx, self.upvars, borrowed_place.as_ref(), body);
let category = if let Some(field) = field {
ConstraintCategory::ClosureUpvar(field)
} else {
@ -2844,7 +2784,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements {
constraint_conversion::ConstraintConversion::new(
self.infcx,
self.borrowck_context.universal_regions,
self.universal_regions,
self.region_bound_pairs,
self.implicit_region_bound,
self.param_env,
@ -2852,7 +2792,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
locations,
self.body.span, // irrelevant; will be overridden.
ConstraintCategory::Boring, // same as above.
self.borrowck_context.constraints,
self.constraints,
)
.apply_closure_requirements(closure_requirements, def_id.to_def_id(), args);
}

View File

@ -240,11 +240,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
fn create_next_universe(&mut self) -> ty::UniverseIndex {
let universe = self.type_checker.infcx.create_next_universe();
self.type_checker
.borrowck_context
.constraints
.universe_causes
.insert(universe, self.universe_info.clone());
self.type_checker.constraints.universe_causes.insert(universe, self.universe_info.clone());
universe
}
@ -264,11 +260,8 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
#[instrument(skip(self), level = "debug")]
fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
let reg = self
.type_checker
.borrowck_context
.constraints
.placeholder_region(self.type_checker.infcx, placeholder);
let reg =
self.type_checker.constraints.placeholder_region(self.type_checker.infcx, placeholder);
let reg_info = match placeholder.bound.kind {
ty::BoundRegionKind::BrAnon => sym::anon,
@ -294,19 +287,17 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> {
sub: ty::Region<'tcx>,
info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
) {
let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
self.type_checker.borrowck_context.constraints.outlives_constraints.push(
OutlivesConstraint {
sup,
sub,
locations: self.locations,
span: self.locations.span(self.type_checker.body),
category: self.category,
variance_info: info,
from_closure: false,
},
);
let sub = self.type_checker.universal_regions.to_region_vid(sub);
let sup = self.type_checker.universal_regions.to_region_vid(sup);
self.type_checker.constraints.outlives_constraints.push(OutlivesConstraint {
sup,
sub,
locations: self.locations,
span: self.locations.span(self.type_checker.body),
category: self.category,
variance_info: info,
from_closure: false,
});
}
}