Skip to content

Commit

Permalink
bundle up "canonical instantiation" with infcx creation
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Oct 15, 2018
1 parent 110b3b9 commit fd046a2
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 30 deletions.
19 changes: 13 additions & 6 deletions src/librustc/infer/canonical/mod.rs
Expand Up @@ -225,19 +225,26 @@ 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>,
) -> (T, CanonicalVarValues<'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);
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/infer/canonical/query_result.rs
Expand Up @@ -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)
Expand Down
25 changes: 23 additions & 2 deletions src/librustc/infer/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
17 changes: 7 additions & 10 deletions src/librustc_traits/dropck_outlives.rs
Expand Up @@ -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![],
Expand Down
15 changes: 6 additions & 9 deletions src/librustc_traits/evaluate_obligation.rs
Expand Up @@ -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);
Expand Down

0 comments on commit fd046a2

Please sign in to comment.