diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-09-24 15:15:25 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-10-15 08:57:22 -0400 |
| commit | fd046a2ede1f83383e7a4a5f653f75550db91ea4 (patch) | |
| tree | aab943040ef00a0e14a8d11801229d16595625c4 | |
| parent | 110b3b971eb0fcf90c4d2836968f4d23fa396e5d (diff) | |
| download | rust-fd046a2ede1f83383e7a4a5f653f75550db91ea4.tar.gz rust-fd046a2ede1f83383e7a4a5f653f75550db91ea4.zip | |
bundle up "canonical instantiation" with infcx creation
| -rw-r--r-- | src/librustc/infer/canonical/mod.rs | 19 | ||||
| -rw-r--r-- | src/librustc/infer/canonical/query_result.rs | 4 | ||||
| -rw-r--r-- | src/librustc/infer/mod.rs | 25 | ||||
| -rw-r--r-- | src/librustc_traits/dropck_outlives.rs | 17 | ||||
| -rw-r--r-- | src/librustc_traits/evaluate_obligation.rs | 15 |
5 files changed, 50 insertions, 30 deletions
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs index 85aa4f62f21..6e9d87c089b 100644 --- a/src/librustc/infer/canonical/mod.rs +++ b/src/librustc/infer/canonical/mod.rs @@ -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 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { 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); diff --git a/src/librustc/infer/canonical/query_result.rs b/src/librustc/infer/canonical/query_result.rs index a327f1f5c9d..d75d39201c4 100644 --- a/src/librustc/infer/canonical/query_result.rs +++ b/src/librustc/infer/canonical/query_result.rs @@ -64,9 +64,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtBuilder<'cx, 'gcx, 'tcx> { 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) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 291b46edccf..0c161536831 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -20,6 +20,7 @@ pub use ty::IntVarValue; 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 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { 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, diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 2996fe03200..1745679bc27 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -30,19 +30,16 @@ crate fn provide(p: &mut Providers) { 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![], diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index b5ee346569a..4487bb11f6d 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -24,16 +24,13 @@ crate fn provide(p: &mut Providers) { 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); |
