about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-09-17 12:15:48 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-09-26 09:38:26 -0400
commit9b63dcc7731e1023c525e795ba36472a3e4bd21b (patch)
tree11fc4c0173b32d39cfc57d106a843a30940489f8
parentb0e1fec33251c02080403f89a11a78ba452464c0 (diff)
downloadrust-9b63dcc7731e1023c525e795ba36472a3e4bd21b.tar.gz
rust-9b63dcc7731e1023c525e795ba36472a3e4bd21b.zip
split out getting the declared bounds from the env versus trait
Right now, we just concatenate them
-rw-r--r--src/librustc/infer/outlives/obligations.rs30
-rw-r--r--src/librustc/infer/outlives/verify.rs31
2 files changed, 38 insertions, 23 deletions
diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs
index c19c8f57d2d..2db1c5e3d30 100644
--- a/src/librustc/infer/outlives/obligations.rs
+++ b/src/librustc/infer/outlives/obligations.rs
@@ -391,16 +391,18 @@ where
         // Compute the bounds we can derive from the environment or trait
         // definition.  We know that the projection outlives all the
         // regions in this list.
-        let env_bounds = self.verify_bound.projection_declared_bounds(projection_ty);
+        let mut declared_bounds = self.verify_bound
+            .projection_declared_bounds_from_env(projection_ty);
 
-        debug!("projection_must_outlive: env_bounds={:?}", env_bounds);
+        declared_bounds.extend(
+            self.verify_bound
+                .projection_declared_bounds_from_trait(projection_ty),
+        );
 
-        // If we know that the projection outlives 'static, then we're
-        // done here.
-        if env_bounds.contains(&&ty::ReStatic) {
-            debug!("projection_must_outlive: 'static as declared bound");
-            return;
-        }
+        debug!(
+            "projection_must_outlive: declared_bounds={:?}",
+            declared_bounds
+        );
 
         // If declared bounds list is empty, the only applicable rule is
         // OutlivesProjectionComponent. If there are inference variables,
@@ -417,7 +419,7 @@ where
         // inference variables, we use a verify constraint instead of adding
         // edges, which winds up enforcing the same condition.
         let needs_infer = projection_ty.needs_infer();
-        if env_bounds.is_empty() && needs_infer {
+        if declared_bounds.is_empty() && needs_infer {
             debug!("projection_must_outlive: no declared bounds");
 
             for component_ty in projection_ty.substs.types() {
@@ -440,8 +442,12 @@ where
         // the requirement that `'b:'r`
         // - OutlivesProjectionComponent: this would require `'b:'r` in addition to
         // other conditions
-        if !env_bounds.is_empty() && env_bounds[1..].iter().all(|b| *b == env_bounds[0]) {
-            let unique_bound = env_bounds[0];
+        if !declared_bounds.is_empty()
+            && declared_bounds[1..]
+                .iter()
+                .all(|b| *b == declared_bounds[0])
+        {
+            let unique_bound = declared_bounds[0];
             debug!(
                 "projection_must_outlive: unique declared bound = {:?}",
                 unique_bound
@@ -449,7 +455,7 @@ where
             if projection_ty
                 .substs
                 .regions()
-                .any(|r| env_bounds.contains(&r))
+                .any(|r| declared_bounds.contains(&r))
             {
                 debug!("projection_must_outlive: unique declared bound appears in trait ref");
                 self.delegate
diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs
index 3a1e2057931..cd4f3c3e5dc 100644
--- a/src/librustc/infer/outlives/verify.rs
+++ b/src/librustc/infer/outlives/verify.rs
@@ -72,22 +72,26 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
         VerifyBound::AnyRegion(param_bounds)
     }
 
+    /// Given a projection like `T::Item`, searches the environment
+    /// for where-clauses like `T::Item: 'a`. Returns the set of
+    /// regions `'a` that it finds.  This is a "conservative" check --
+    /// it may not find all applicable bounds, but all the bounds it
+    /// returns can be relied upon.
+    pub fn projection_declared_bounds_from_env(
+        &self,
+        projection_ty: ty::ProjectionTy<'tcx>,
+    ) -> Vec<ty::Region<'tcx>> {
+        self.declared_generic_bounds_from_env(GenericKind::Projection(projection_ty))
+    }
+
     /// Searches the where clauses in scope for regions that
     /// `projection_ty` is known to outlive. Currently requires an
     /// exact match.
-    pub fn projection_declared_bounds(
+    pub fn projection_declared_bounds_from_trait(
         &self,
         projection_ty: ty::ProjectionTy<'tcx>,
     ) -> Vec<ty::Region<'tcx>> {
-        // First assemble bounds from where clauses and traits.
-
-        let mut declared_bounds =
-            self.declared_generic_bounds_from_env(GenericKind::Projection(projection_ty));
-
-        declared_bounds
-            .extend_from_slice(&self.declared_projection_bounds_from_trait(projection_ty));
-
-        declared_bounds
+        self.declared_projection_bounds_from_trait(projection_ty)
     }
 
     pub fn projection_bound(
@@ -99,7 +103,12 @@ impl<'cx, 'gcx, 'tcx> VerifyBoundCx<'cx, 'gcx, 'tcx> {
             projection_ty
         );
 
-        let declared_bounds = self.projection_declared_bounds(projection_ty);
+        let mut declared_bounds =
+            self.projection_declared_bounds_from_env(projection_ty);
+
+        declared_bounds.extend(
+            self.projection_declared_bounds_from_trait(projection_ty)
+        );
 
         debug!("projection_bound: declared_bounds = {:?}", declared_bounds);