about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-03-23 04:19:34 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-04-23 13:28:14 -0400
commitc8a52850cffd1e13e1f695451127f981345c72ec (patch)
tree0dd1142d1404557720f6c6da8887d4ad770054f4
parent3aa1085cfc3b39d4c2b03642c79f1557a2424d87 (diff)
downloadrust-c8a52850cffd1e13e1f695451127f981345c72ec.tar.gz
rust-c8a52850cffd1e13e1f695451127f981345c72ec.zip
create a `QueryRegionConstraint` type
Chalk wants to be able to pass these constraints around. Also, the
form we were using in our existing queries was not as general as we
are going to need.
-rw-r--r--src/librustc/ich/impls_ty.rs4
-rw-r--r--src/librustc/infer/canonical.rs71
-rw-r--r--src/librustc_traits/util.rs40
3 files changed, 45 insertions, 70 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 70c152b40c0..acb1d2272ef 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -1352,10 +1352,6 @@ impl_stable_hash_for!(
     }
 );
 
-impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
-    region_outlives, ty_outlives
-});
-
 impl_stable_hash_for!(enum infer::canonical::Certainty {
     Proven, Ambiguous
 });
diff --git a/src/librustc/infer/canonical.rs b/src/librustc/infer/canonical.rs
index 8ea6eb005a1..25f8b5d8c9c 100644
--- a/src/librustc/infer/canonical.rs
+++ b/src/librustc/infer/canonical.rs
@@ -42,7 +42,6 @@ use traits::{Obligation, ObligationCause, PredicateObligation};
 use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
 use ty::subst::{Kind, UnpackedKind};
 use ty::fold::{TypeFoldable, TypeFolder};
-use util::captures::Captures;
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
@@ -121,7 +120,7 @@ pub enum CanonicalTyVarKind {
 #[derive(Clone, Debug)]
 pub struct QueryResult<'tcx, R> {
     pub var_values: CanonicalVarValues<'tcx>,
-    pub region_constraints: QueryRegionConstraints<'tcx>,
+    pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
     pub certainty: Certainty,
     pub value: R,
 }
@@ -181,12 +180,7 @@ impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> {
     }
 }
 
-/// Subset of `RegionConstraintData` produced by trait query.
-#[derive(Clone, Debug, Default)]
-pub struct QueryRegionConstraints<'tcx> {
-    pub region_outlives: Vec<(Region<'tcx>, Region<'tcx>)>,
-    pub ty_outlives: Vec<(Ty<'tcx>, Region<'tcx>)>,
-}
+pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
 
 /// Trait implemented by values that can be canonicalized. It mainly
 /// serves to identify the interning table we will use.
@@ -382,35 +376,29 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
         &'a self,
         cause: &'a ObligationCause<'tcx>,
         param_env: ty::ParamEnv<'tcx>,
-        unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
+        unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
         result_subst: &'a CanonicalVarValues<'tcx>,
-    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
-        let QueryRegionConstraints {
-            region_outlives,
-            ty_outlives,
-        } = unsubstituted_region_constraints;
-
-        let region_obligations = region_outlives.iter().map(move |(r1, r2)| {
-            let r1 = substitute_value(self.tcx, result_subst, r1);
-            let r2 = substitute_value(self.tcx, result_subst, r2);
-            Obligation::new(
-                cause.clone(),
-                param_env,
-                ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
-            )
-        });
-
-        let ty_obligations = ty_outlives.iter().map(move |(t1, r2)| {
-            let t1 = substitute_value(self.tcx, result_subst, t1);
+    ) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
+        Box::new(unsubstituted_region_constraints.iter().map(move |constraint| {
+            let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
+            let k1 = substitute_value(self.tcx, result_subst, k1);
             let r2 = substitute_value(self.tcx, result_subst, r2);
-            Obligation::new(
-                cause.clone(),
-                param_env,
-                ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
-            )
-        });
-
-        region_obligations.chain(ty_obligations)
+            match k1.unpack() {
+                UnpackedKind::Lifetime(r1) =>
+                    Obligation::new(
+                        cause.clone(),
+                        param_env,
+                        ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
+                    ),
+
+                UnpackedKind::Type(t1) =>
+                    Obligation::new(
+                        cause.clone(),
+                        param_env,
+                        ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
+                    ),
+            }
+        })) as Box<dyn Iterator<Item = _>>
     }
 
     /// Given two sets of values for the same set of canonical variables, unify them.
@@ -914,19 +902,6 @@ BraceStructTypeFoldableImpl! {
 }
 
 BraceStructTypeFoldableImpl! {
-    impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
-        region_outlives, ty_outlives
-    }
-}
-
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
-        type Lifted = QueryRegionConstraints<'tcx>;
-        region_outlives, ty_outlives
-    }
-}
-
-BraceStructTypeFoldableImpl! {
     impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> {
         var_values, region_constraints, certainty, value
     } where R: TypeFoldable<'tcx>,
diff --git a/src/librustc_traits/util.rs b/src/librustc_traits/util.rs
index bff070ab73d..f25906a7bca 100644
--- a/src/librustc_traits/util.rs
+++ b/src/librustc_traits/util.rs
@@ -9,8 +9,7 @@
 // except according to those terms.
 
 use rustc::infer::InferCtxt;
-use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints,
-                              QueryResult};
+use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult};
 use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
 use rustc::traits::{FulfillmentContext, TraitEngine};
 use rustc::traits::query::NoSolution;
@@ -62,7 +61,7 @@ where
 
     let region_obligations = infcx.take_registered_region_obligations();
 
-    let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| {
+    let region_constraints = infcx.with_region_constraints(|region_constraints| {
         let RegionConstraintData {
             constraints,
             verifys,
@@ -72,24 +71,32 @@ where
         assert!(verifys.is_empty());
         assert!(givens.is_empty());
 
-        let region_outlives: Vec<_> = constraints
+        let mut outlives: Vec<_> = constraints
             .into_iter()
             .map(|(k, _)| match *k {
-                Constraint::VarSubVar(v1, v2) => {
-                    (tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2)))
+                Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
+                    tcx.mk_region(ty::ReVar(v1)).into(),
+                    tcx.mk_region(ty::ReVar(v2)),
+                ),
+                Constraint::VarSubReg(v1, r2) => {
+                    ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2)
                 }
-                Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2),
-                Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))),
-                Constraint::RegSubReg(r1, r2) => (r1, r2),
+                Constraint::RegSubVar(r1, v2) => {
+                    ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2)))
+                }
+                Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2),
             })
+            .map(ty::Binder) // no bound regions in the code above
             .collect();
 
-        let ty_outlives: Vec<_> = region_obligations
-            .into_iter()
-            .map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
-            .collect();
+        outlives.extend(
+            region_obligations
+                .into_iter()
+                .map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
+                .map(ty::Binder) // no bound regions in the code above
+        );
 
-        (region_outlives, ty_outlives)
+        outlives
     });
 
     let certainty = if ambig_errors.is_empty() {
@@ -100,10 +107,7 @@ where
 
     let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
         var_values: inference_vars,
-        region_constraints: QueryRegionConstraints {
-            region_outlives,
-            ty_outlives,
-        },
+        region_constraints,
         certainty,
         value: answer,
     });