]> git.lizzy.rs Git - rust.git/commitdiff
bundle up "canonical instantiation" with infcx creation
authorNiko Matsakis <niko@alum.mit.edu>
Mon, 24 Sep 2018 19:15:25 +0000 (15:15 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Mon, 15 Oct 2018 12:57:22 +0000 (08:57 -0400)
src/librustc/infer/canonical/mod.rs
src/librustc/infer/canonical/query_result.rs
src/librustc/infer/mod.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_traits/evaluate_obligation.rs

index 85aa4f62f214c24f6e477c4d021586fc0beca513..6e9d87c089b4d9ee867fd3db9740004c74126cc1 100644 (file)
@@ -225,12 +225,16 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
     /// inference variables and applies it to the canonical value.
     /// Returns both the instantiated result *and* the substitution S.
     ///
-    /// This is useful at the start of a query: it basically brings
-    /// the canonical value "into scope" within your new infcx. At the
-    /// end of processing, the substitution S (once canonicalized)
-    /// then represents the values that you computed for each of the
-    /// canonical inputs to your query.
-    pub fn instantiate_canonical_with_fresh_inference_vars<T>(
+    /// This is only meant to be invoked as part of constructing an
+    /// inference context at the start of a query (see
+    /// `InferCtxtBuilder::enter_with_canonical`).  It basically
+    /// brings the canonical value "into scope" within your new infcx.
+    ///
+    /// At the end of processing, the substitution S (once
+    /// canonicalized) then represents the values that you computed
+    /// for each of the canonical inputs to your query.
+
+    pub(in infer) fn instantiate_canonical_with_fresh_inference_vars<T>(
         &self,
         span: Span,
         canonical: &Canonical<'tcx, T>,
@@ -238,6 +242,9 @@ pub fn instantiate_canonical_with_fresh_inference_vars<T>(
     where
         T: TypeFoldable<'tcx>,
     {
+        assert_eq!(self.universe(), ty::UniverseIndex::ROOT, "infcx not newly created");
+        assert_eq!(self.type_variables.borrow().num_vars(), 0, "infcx not newly created");
+
         let canonical_inference_vars =
             self.fresh_inference_vars_for_canonical_vars(span, canonical.variables);
         let result = canonical.substitute(self.tcx, &canonical_inference_vars);
index a327f1f5c9d50b462a5e1319da2eb57ac9d879cf..d75d39201c49e78a232b0f71ed09867e92e29848 100644 (file)
@@ -64,9 +64,7 @@ pub fn enter_canonical_trait_query<K, R>(
         K: TypeFoldable<'tcx>,
         R: Debug + Lift<'gcx> + TypeFoldable<'tcx>,
     {
-        self.enter(|ref infcx| {
-            let (key, canonical_inference_vars) =
-                infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_key);
+        self.enter_with_canonical(DUMMY_SP, canonical_key, |ref infcx, key, canonical_inference_vars| {
             let fulfill_cx = &mut FulfillmentContext::new();
             let value = operation(infcx, fulfill_cx, key)?;
             infcx.make_canonicalized_query_result(canonical_inference_vars, value, fulfill_cx)
index 291b46edccfb2342b6b9f981fd4865d1d95ba4b7..0c161536831753395384d86ce88b49e8adda45a3 100644 (file)
@@ -20,6 +20,7 @@
 use arena::SyncDroplessArena;
 use errors::DiagnosticBuilder;
 use hir::def_id::DefId;
+use infer::canonical::{Canonical, CanonicalVarValues};
 use middle::free_region::RegionRelations;
 use middle::lang_items;
 use middle::region;
@@ -494,9 +495,29 @@ pub fn with_fresh_in_progress_tables(mut self, table_owner: DefId) -> Self {
         self
     }
 
-    pub fn enter<F, R>(&'tcx mut self, f: F) -> R
+    /// Given a canonical value `C` as a starting point, create an
+    /// inference context that contains each of the bound values
+    /// within instantiated as a fresh variable. The `f` closure is
+    /// invoked with the new infcx, along with the instantiated value
+    /// `V` and a substitution `S`.  This substitution `S` maps from
+    /// the bound values in `C` to their instantiated values in `V`
+    /// (in other words, `S(C) = V`).
+    pub fn enter_with_canonical<T, R>(
+        &'tcx mut self,
+        span: Span,
+        canonical: &Canonical<'tcx, T>,
+        f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>, T, CanonicalVarValues<'tcx>) -> R,
+    ) -> R
     where
-        F: for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R,
+        T: TypeFoldable<'tcx>,
+    {
+        self.enter(|infcx| {
+            let (value, subst) = infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
+            f(infcx, value, subst)
+        })
+    }
+
+    pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R
     {
         let InferCtxtBuilder {
             global_tcx,
index 2996fe03200428cb8ead7057131aa1f186bbf367..1745679bc27f1c4d0d020dbd24456e300187ee7f 100644 (file)
 
 fn dropck_outlives<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
-    goal: CanonicalTyGoal<'tcx>,
+    canonical_goal: CanonicalTyGoal<'tcx>,
 ) -> Result<Lrc<Canonical<'tcx, QueryResult<'tcx, DropckOutlivesResult<'tcx>>>>, NoSolution> {
-    debug!("dropck_outlives(goal={:#?})", goal);
+    debug!("dropck_outlives(goal={:#?})", canonical_goal);
 
-    tcx.infer_ctxt().enter(|ref infcx| {
+    tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &canonical_goal, |ref infcx, goal, canonical_inference_vars| {
         let tcx = infcx.tcx;
-        let (
-            ParamEnvAnd {
-                param_env,
-                value: for_ty,
-            },
-            canonical_inference_vars,
-        ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
+        let ParamEnvAnd {
+            param_env,
+            value: for_ty,
+        } = goal;
 
         let mut result = DropckOutlivesResult {
             kinds: vec![],
index b5ee346569a694ec2e73c22f92b46e19d11f1df3..4487bb11f6daf56bc684b1393b363f010092ce5f 100644 (file)
 
 fn evaluate_obligation<'tcx>(
     tcx: TyCtxt<'_, 'tcx, 'tcx>,
-    goal: CanonicalPredicateGoal<'tcx>,
+    canonical_goal: CanonicalPredicateGoal<'tcx>,
 ) -> Result<EvaluationResult, OverflowError> {
-    tcx.infer_ctxt().enter(|ref infcx| {
-        let (
-            ParamEnvAnd {
-                param_env,
-                value: predicate,
-            },
-            _canonical_inference_vars,
-        ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal);
+    tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &canonical_goal, |ref infcx, goal, _canonical_inference_vars| {
+        let ParamEnvAnd {
+            param_env,
+            value: predicate,
+        } = goal;
 
         let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical);
         let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate);