]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc_mir/borrow_check/nll/constraint_generation.rs
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / librustc_mir / borrow_check / nll / constraint_generation.rs
index d34e9434fbf2a0352a5cc4ec36b796f5cf1436f0..72db9f8da987251f1e69bf71da2de0167349b1d2 100644 (file)
@@ -11,6 +11,8 @@
 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;
@@ -20,10 +22,8 @@ use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
 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>,
@@ -32,6 +32,7 @@ pub(super) fn generate_constraints<'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,
@@ -42,6 +43,8 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
         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);
     }
@@ -97,6 +100,13 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         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) {
@@ -202,7 +212,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
                 self.add_reborrow_constraint(location, region, borrowed_place);
             }
 
-            _ => { }
+            _ => {}
         }
 
         self.super_rvalue(rvalue, location);
@@ -218,6 +228,42 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
 }
 
 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
@@ -263,7 +309,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
 
                     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,