about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-01 10:13:13 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-10-27 08:41:12 -0400
commit784746f57e6e9d76f4ecc0415e8ab926a81ce37e (patch)
treef60afcbd64473abc60bef1c4b4a8ffee9933801e
parent018c515f077597ad45f85d962a49ab6fbc5421ac (diff)
downloadrust-784746f57e6e9d76f4ecc0415e8ab926a81ce37e.tar.gz
rust-784746f57e6e9d76f4ecc0415e8ab926a81ce37e.zip
convert placeholder region vids in NLL mode as we see them
-rw-r--r--src/librustc_mir/borrow_check/nll/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs1
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/mod.rs5
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs54
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs5
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs46
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs14
7 files changed, 88 insertions, 38 deletions
diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs
index 03cdb5f4cb8..0c4140caee8 100644
--- a/src/librustc_mir/borrow_check/nll/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/mod.rs
@@ -134,6 +134,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let var_origins = infcx.take_region_var_origins();
     let MirTypeckRegionConstraints {
         placeholder_indices,
+        placeholder_index_to_region: _,
         mut liveness_constraints,
         outlives_constraints,
         closure_bounds_mapping,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index ccb44c670f7..64135195637 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -594,6 +594,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     // Finds some region R such that `fr1: R` and `R` is live at
     // `elem`.
     crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
+        debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem);
         // Find all paths
         let (_path, r) =
             self.find_constraint_paths_between_regions(fr1, |r| {
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
index 50fd4afcd7e..0e44c8b36a9 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs
@@ -1226,6 +1226,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         );
 
         let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
+        debug!(
+            "check_bound_universal_region: longer_fr_scc={:?}",
+            longer_fr_scc,
+        );
 
         // If we have some bound universal region `'a`, then the only
         // elements it can contain is itself -- we don't know anything
@@ -1242,6 +1246,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             Some(v) => v,
             None => return,
         };
+        debug!("check_bound_universal_region: error_element = {:?}", error_element);
 
         // Find the region that introduced this `error_element`.
         let error_region = match error_element {
diff --git a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
index 994f20a011d..5904138ef60 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
@@ -8,21 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
+use borrow_check::nll::constraints::OutlivesConstraint;
 use borrow_check::nll::region_infer::TypeTest;
-use borrow_check::nll::type_check::Locations;
+use borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
 use borrow_check::nll::universal_regions::UniversalRegions;
+use borrow_check::nll::ToRegionVid;
 use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
-use rustc::infer::{self, SubregionOrigin};
+use rustc::infer::{self, InferCtxt, SubregionOrigin};
 use rustc::mir::ConstraintCategory;
 use rustc::ty::subst::UnpackedKind;
 use rustc::ty::{self, TyCtxt};
 use syntax_pos::DUMMY_SP;
 
 crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     universal_regions: &'a UniversalRegions<'tcx>,
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
@@ -30,32 +32,30 @@ crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     locations: Locations,
     category: ConstraintCategory,
-    outlives_constraints: &'a mut ConstraintSet,
-    type_tests: &'a mut Vec<TypeTest<'tcx>>,
+    constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 }
 
 impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     crate fn new(
-        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
         universal_regions: &'a UniversalRegions<'tcx>,
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
         implicit_region_bound: Option<ty::Region<'tcx>>,
         param_env: ty::ParamEnv<'tcx>,
         locations: Locations,
         category: ConstraintCategory,
-        outlives_constraints: &'a mut ConstraintSet,
-        type_tests: &'a mut Vec<TypeTest<'tcx>>,
+        constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
     ) -> Self {
         Self {
-            tcx,
+            infcx,
+            tcx: infcx.tcx,
             universal_regions,
             region_bound_pairs,
             implicit_region_bound,
             param_env,
             locations,
             category,
-            outlives_constraints,
-            type_tests,
+            constraints,
         }
     }
 
@@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
     }
 
     fn verify_to_type_test(
-        &self,
+        &mut self,
         generic_kind: GenericKind<'tcx>,
         region: ty::Region<'tcx>,
         verify_bound: VerifyBound<'tcx>,
@@ -128,22 +128,30 @@ impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
         }
     }
 
-    fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
-        self.universal_regions.to_region_vid(r)
+    fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
+        if let ty::RePlaceholder(placeholder) = r {
+            self.constraints
+                .placeholder_region(self.infcx, *placeholder)
+                .to_region_vid()
+        } else {
+            self.universal_regions.to_region_vid(r)
+        }
     }
 
     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
-        self.outlives_constraints.push(OutlivesConstraint {
-            locations: self.locations,
-            category: self.category,
-            sub,
-            sup,
-        });
+        self.constraints
+            .outlives_constraints
+            .push(OutlivesConstraint {
+                locations: self.locations,
+                category: self.category,
+                sub,
+                sup,
+            });
     }
 
     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
         debug!("add_type_test(type_test={:?})", type_test);
-        self.type_tests.push(type_test);
+        self.constraints.type_tests.push(type_test);
     }
 }
 
@@ -156,8 +164,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
         a: ty::Region<'tcx>,
         b: ty::Region<'tcx>,
     ) {
-        let b = self.universal_regions.to_region_vid(b);
-        let a = self.universal_regions.to_region_vid(a);
+        let b = self.to_region_vid(b);
+        let a = self.to_region_vid(a);
         self.add_outlives(b, a);
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
index f8c839e4d3f..3d0f3d9fc7d 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/free_region_relations.rs
@@ -271,15 +271,14 @@ impl UniversalRegionRelationsBuilder<'cx, 'gcx, 'tcx> {
 
         for data in constraint_sets {
             constraint_conversion::ConstraintConversion::new(
-                self.infcx.tcx,
+                self.infcx,
                 &self.universal_regions,
                 &self.region_bound_pairs,
                 self.implicit_region_bound,
                 self.param_env,
                 Locations::All(DUMMY_SP),
                 ConstraintCategory::Internal,
-                &mut self.constraints.outlives_constraints,
-                &mut self.constraints.type_tests,
+                &mut self.constraints,
             ).convert_all(&data);
         }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index bcf73c5c644..eae41c81ff2 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -16,6 +16,7 @@ use borrow_check::location::LocationTable;
 use borrow_check::nll::constraints::{ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::values::LivenessValues;
+use borrow_check::nll::region_infer::values::PlaceholderIndex;
 use borrow_check::nll::region_infer::values::PlaceholderIndices;
 use borrow_check::nll::region_infer::values::RegionValueElements;
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
@@ -28,11 +29,12 @@ use borrow_check::nll::ToRegionVid;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
 use dataflow::MaybeInitializedPlaces;
+use either::Either;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
-use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
+use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
@@ -44,14 +46,13 @@ use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, Substs, UnpackedKind};
 use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::indexed_vec::IndexVec;
 use std::rc::Rc;
 use std::{fmt, iter};
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 
-use either::Either;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
         $crate::borrow_check::nll::type_check::mirbug(
@@ -127,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
     let implicit_region_bound = infcx.tcx.mk_region(ty::ReVar(universal_regions.fr_fn_body));
     let mut constraints = MirTypeckRegionConstraints {
         placeholder_indices: PlaceholderIndices::default(),
+        placeholder_index_to_region: IndexVec::default(),
         liveness_constraints: LivenessValues::new(elements),
         outlives_constraints: ConstraintSet::default(),
         closure_bounds_mapping: Default::default(),
@@ -738,8 +740,20 @@ crate struct MirTypeckResults<'tcx> {
 /// A collection of region constraints that must be satisfied for the
 /// program to be considered well-typed.
 crate struct MirTypeckRegionConstraints<'tcx> {
+    /// Maps from a `ty::Placeholder` to the corresponding
+    /// `PlaceholderIndex` bit that we will use for it.
+    ///
+    /// To keep everything in sync, do not insert this set
+    /// directly. Instead, use the `placeholder_region` helper.
     crate placeholder_indices: PlaceholderIndices,
 
+    /// Each time we add a placeholder to `placeholder_indices`, we
+    /// also create a corresponding "representative" region vid for
+    /// that wraps it. This vector tracks those. This way, when we
+    /// convert the same `ty::RePlaceholder(p)` twice, we can map to
+    /// the same underlying `RegionVid`.
+    crate placeholder_index_to_region: IndexVec<PlaceholderIndex, ty::Region<'tcx>>,
+
     /// In general, the type-checker is not responsible for enforcing
     /// liveness constraints; this job falls to the region inferencer,
     /// which performs a liveness analysis. However, in some limited
@@ -757,6 +771,25 @@ crate struct MirTypeckRegionConstraints<'tcx> {
     crate type_tests: Vec<TypeTest<'tcx>>,
 }
 
+impl MirTypeckRegionConstraints<'tcx> {
+    fn placeholder_region(
+        &mut self,
+        infcx: &InferCtxt<'_, '_, 'tcx>,
+        placeholder: ty::Placeholder,
+    ) -> ty::Region<'tcx> {
+        let placeholder_index = self.placeholder_indices.insert(placeholder);
+        match self.placeholder_index_to_region.get(placeholder_index) {
+            Some(&v) => v,
+            None => {
+                let origin = NLLRegionVariableOrigin::Placeholder(placeholder);
+                let region = infcx.next_nll_region_var(origin);
+                self.placeholder_index_to_region.push(region);
+                region
+            }
+        }
+    }
+}
+
 /// The `Locations` type summarizes *where* region constraints are
 /// required to hold. Normally, this is at a particular point which
 /// created the obligation, but for constraints that the user gave, we
@@ -886,15 +919,14 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
 
         if let Some(ref mut borrowck_context) = self.borrowck_context {
             constraint_conversion::ConstraintConversion::new(
-                self.infcx.tcx,
+                self.infcx,
                 borrowck_context.universal_regions,
                 self.region_bound_pairs,
                 self.implicit_region_bound,
                 self.param_env,
                 locations,
                 category,
-                &mut borrowck_context.constraints.outlives_constraints,
-                &mut borrowck_context.constraints.type_tests,
+                &mut borrowck_context.constraints,
             ).convert_all(&data);
         }
     }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index 5c699b5295d..b82efb29f6e 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -76,16 +76,20 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
     }
 
     fn next_existential_region_var(&mut self) -> ty::Region<'tcx> {
-        let origin = NLLRegionVariableOrigin::Existential;
-        self.infcx.next_nll_region_var(origin)
+        if let Some(_) = &mut self.borrowck_context {
+            let origin = NLLRegionVariableOrigin::Existential;
+            self.infcx.next_nll_region_var(origin)
+        } else {
+            self.infcx.tcx.types.re_erased
+        }
     }
 
     fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> {
-        let origin = NLLRegionVariableOrigin::Placeholder(placeholder);
         if let Some(borrowck_context) = &mut self.borrowck_context {
-            borrowck_context.constraints.placeholder_indices.insert(placeholder);
+            borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
+        } else {
+            self.infcx.tcx.types.re_erased
         }
-        self.infcx.next_nll_region_var(origin)
     }
 
     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {