use borrow_check::borrow_set::BorrowSet;
use borrow_check::location::LocationTable;
use borrow_check::nll::facts::AllFacts;
+use borrow_check::nll::region_infer::{Cause, RegionInferenceContext};
+use borrow_check::nll::ToRegionVid;
use rustc::hir;
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::{Local, PlaceProjection, ProjectionElem, Statement, Terminator};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::subst::Substs;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts};
-
-use super::region_infer::{Cause, RegionInferenceContext};
-use super::ToRegionVid;
+use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts};
+use std::iter;
pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
location_table: &LocationTable,
mir: &Mir<'tcx>,
borrow_set: &BorrowSet<'tcx>,
+ liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)],
) {
let mut cg = ConstraintGeneration {
borrow_set,
mir,
};
+ cg.add_region_liveness_constraints_from_type_check(liveness_set_from_typeck);
+
for (bb, data) in mir.basic_blocks().iter_enumerated() {
cg.visit_basic_block_data(bb, data);
}
self.super_ty(ty);
}
+ /// We sometimes have `generator_substs` within an rvalue, or within a
+ /// call. Make them live at the location where they appear.
+ fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
+ self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location));
+ self.super_generator_substs(substs);
+ }
+
/// We sometimes have `closure_substs` within an rvalue, or within a
/// call. Make them live at the location where they appear.
fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
self.add_reborrow_constraint(location, region, borrowed_place);
}
- _ => { }
+ _ => {}
}
self.super_rvalue(rvalue, location);
}
impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
+ /// The MIR type checker generates region liveness constraints
+ /// that we also have to respect.
+ fn add_region_liveness_constraints_from_type_check(
+ &mut self,
+ liveness_set: &[(ty::Region<'tcx>, Location, Cause)],
+ ) {
+ debug!(
+ "add_region_liveness_constraints_from_type_check(liveness_set={} items)",
+ liveness_set.len(),
+ );
+
+ let ConstraintGeneration {
+ regioncx,
+ location_table,
+ all_facts,
+ ..
+ } = self;
+
+ for (region, location, cause) in liveness_set {
+ debug!("generate: {:#?} is live at {:#?}", region, location);
+ let region_vid = regioncx.to_region_vid(region);
+ regioncx.add_live_point(region_vid, *location, &cause);
+ }
+
+ if let Some(all_facts) = all_facts {
+ all_facts
+ .region_live_at
+ .extend(liveness_set.into_iter().flat_map(|(region, location, _)| {
+ let r = regioncx.to_region_vid(region);
+ let p1 = location_table.start_index(*location);
+ let p2 = location_table.mid_index(*location);
+ iter::once((r, p1)).chain(iter::once((r, p2)))
+ }));
+ }
+ }
+
/// Some variable with type `live_ty` is "regular live" at
/// `location` -- i.e., it may be used later. This means that all
/// regions appearing in the type `live_ty` must be live at
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
match base_ty.sty {
- ty::TyRef(ref_region, ty::TypeAndMut { ty: _, mutbl }) => {
+ ty::TyRef(ref_region, _, mutbl) => {
let span = self.mir.source_info(location).span;
self.regioncx.add_outlives(
span,