]> git.lizzy.rs Git - rust.git/commitdiff
create a `QueryRegionConstraint` type
authorNiko Matsakis <niko@alum.mit.edu>
Fri, 23 Mar 2018 08:19:34 +0000 (04:19 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 23 Apr 2018 17:28:14 +0000 (13:28 -0400)
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.

src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical.rs
src/librustc_traits/util.rs

index 70c152b40c0d25fdbc77561268c46efa6c192459..acb1d2272ef52dbd0c704bcb0f9ee459bc85e912 100644 (file)
@@ -1352,10 +1352,6 @@ impl<'tcx, R> for struct infer::canonical::QueryResult<'tcx, R> {
     }
 );
 
-impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
-    region_outlives, ty_outlives
-});
-
 impl_stable_hash_for!(enum infer::canonical::Certainty {
     Proven, Ambiguous
 });
index 8ea6eb005a140b0eb105e7fbbc839074fccd2837..25f8b5d8c9cc0422f1c7fd288e3fd359bcf116c0 100644 (file)
@@ -42,7 +42,6 @@
 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 @@ pub fn is_ambiguous(&self) -> bool {
     }
 }
 
-/// 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 @@ fn query_region_constraints_into_obligations<'a>(
         &'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.
@@ -913,19 +901,6 @@ impl<'tcx> TypeFoldable<'tcx> for CanonicalVarValues<'tcx> {
     }
 }
 
-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
index bff070ab73de342f06fab3ac80c225277594057e..f25906a7bcad1593e3fff4e003bf671e4c7241d7 100644 (file)
@@ -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 @@
 
     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,
         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() {
 
     let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
         var_values: inference_vars,
-        region_constraints: QueryRegionConstraints {
-            region_outlives,
-            ty_outlives,
-        },
+        region_constraints,
         certainty,
         value: answer,
     });