about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2017-11-04 05:37:18 -0400
committerNiko Matsakis <niko@alum.mit.edu>2017-11-15 16:49:22 -0500
commit3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5 (patch)
tree70f90a92270f5976af4e7445ae399cd18e294dad /src
parente0630e868320bc298da6f93ae06c8b32a829d01b (diff)
downloadrust-3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5.tar.gz
rust-3cc44a569ded1484b0ab4fcc5b8cfd545ea3a4b5.zip
do not invoke `required_region_bounds` in `region_obligations`
Instead, just search the param env predicates directly. This is
equivalent to what we were doing before but more efficient.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/region_obligations.rs40
-rw-r--r--src/librustc/ty/mod.rs6
2 files changed, 40 insertions, 6 deletions
diff --git a/src/librustc/infer/region_obligations.rs b/src/librustc/infer/region_obligations.rs
index 4cd9c3f9ae3..05e14daa281 100644
--- a/src/librustc/infer/region_obligations.rs
+++ b/src/librustc/infer/region_obligations.rs
@@ -470,9 +470,16 @@ impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, 'tcx> {
     ) -> Vec<ty::Region<'tcx>> {
         let tcx = self.tcx();
 
-        // To start, collect bounds from user:
+        // To start, collect bounds from user environment. Note that
+        // parameter environments are already elaborated, so we don't
+        // have to worry about that. Comparing using `==` is a bit
+        // dubious for projections, but it will work for simple cases
+        // like `T` and `T::Item`. It may not work as well for things
+        // like `<T as Foo<'a>>::Item`.
         let mut param_bounds =
-            tcx.required_region_bounds(generic.to_ty(tcx), self.param_env.caller_bounds.to_vec());
+            self.collect_outlives_from_predicate_list(
+                generic.to_ty(tcx),
+                self.param_env.caller_bounds);
 
         // Next, collect regions we scraped from the well-formedness
         // constraints in the fn signature. To do that, we walk the list
@@ -559,10 +566,31 @@ impl<'cx, 'gcx, 'tcx> TypeOutlives<'cx, 'gcx, 'tcx> {
         let trait_predicates = tcx.predicates_of(trait_def_id);
         let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id);
         let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
-        traits::elaborate_predicates(tcx, trait_predicates.predicates)
-            .filter_map(|p| p.to_opt_type_outlives())
-            .filter_map(|p| tcx.no_late_bound_regions(&p))
-            .filter(|p| p.0 == identity_proj)
+        self.collect_outlives_from_predicate_list(
+            identity_proj,
+            traits::elaborate_predicates(tcx, trait_predicates.predicates))
+    }
+
+    /// Searches through a predicate list for a predicate `T: 'a`.
+    ///
+    /// Careful: does not elaborate predicates, and just uses `==`
+    /// when comparing `ty` for equality, so `ty` must be something
+    /// that does not involve inference variables and where you
+    /// otherwise want a precise match.
+    fn collect_outlives_from_predicate_list<I, P>(
+        &self,
+        ty: Ty<'tcx>,
+        predicates: I,
+    ) -> Vec<ty::Region<'tcx>>
+    where
+        I: IntoIterator<Item = P>,
+        P: AsRef<ty::Predicate<'tcx>>,
+    {
+        predicates
+            .into_iter()
+            .filter_map(|p| p.as_ref().to_opt_type_outlives())
+            .filter_map(|p| self.tcx().no_late_bound_regions(&p))
+            .filter(|p| p.0 == ty)
             .map(|p| p.1)
             .collect()
     }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8973d1e0c5a..a9efb042f3d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -904,6 +904,12 @@ pub enum Predicate<'tcx> {
     ConstEvaluatable(DefId, &'tcx Substs<'tcx>),
 }
 
+impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
+    fn as_ref(&self) -> &Predicate<'tcx> {
+        self
+    }
+}
+
 impl<'a, 'gcx, 'tcx> Predicate<'tcx> {
     /// Performs a substitution suitable for going from a
     /// poly-trait-ref to supertraits that must hold if that