extract more helpers from instantiating query result
This commit is contained in:
parent
7bab9f0974
commit
f24e90ec25
@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
use infer::canonical::substitute::substitute_value;
|
use infer::canonical::substitute::substitute_value;
|
||||||
use infer::canonical::{
|
use infer::canonical::{
|
||||||
Canonical, CanonicalVarValues, CanonicalizedQueryResult, Certainty,
|
Canonical, CanonicalVarValues, CanonicalizedQueryResult, Certainty, QueryRegionConstraint,
|
||||||
QueryRegionConstraint, QueryResult,
|
QueryResult,
|
||||||
};
|
};
|
||||||
use infer::region_constraints::{Constraint, RegionConstraintData};
|
use infer::region_constraints::{Constraint, RegionConstraintData};
|
||||||
use infer::{InferCtxt, InferOk, InferResult, RegionObligation};
|
use infer::{InferCtxt, InferOk, InferResult, RegionObligation};
|
||||||
@ -155,12 +155,10 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
where
|
where
|
||||||
R: Debug + TypeFoldable<'tcx>,
|
R: Debug + TypeFoldable<'tcx>,
|
||||||
{
|
{
|
||||||
let InferOk { value: result_subst, mut obligations } = self.query_result_substitution(
|
let InferOk {
|
||||||
cause,
|
value: result_subst,
|
||||||
param_env,
|
mut obligations,
|
||||||
original_values,
|
} = self.query_result_substitution(cause, param_env, original_values, query_result)?;
|
||||||
query_result,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
obligations.extend(self.query_region_constraints_into_obligations(
|
obligations.extend(self.query_region_constraints_into_obligations(
|
||||||
cause,
|
cause,
|
||||||
@ -188,7 +186,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
/// example) we are doing lazy normalization and the value
|
/// example) we are doing lazy normalization and the value
|
||||||
/// assigned to a type variable is unified with an unnormalized
|
/// assigned to a type variable is unified with an unnormalized
|
||||||
/// projection.
|
/// projection.
|
||||||
pub fn query_result_substitution<R>(
|
fn query_result_substitution<R>(
|
||||||
&self,
|
&self,
|
||||||
cause: &ObligationCause<'tcx>,
|
cause: &ObligationCause<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
@ -199,7 +197,49 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
R: Debug + TypeFoldable<'tcx>,
|
R: Debug + TypeFoldable<'tcx>,
|
||||||
{
|
{
|
||||||
debug!(
|
debug!(
|
||||||
"instantiate_query_result(original_values={:#?}, query_result={:#?})",
|
"query_result_substitution(original_values={:#?}, query_result={:#?})",
|
||||||
|
original_values, query_result,
|
||||||
|
);
|
||||||
|
|
||||||
|
let result_subst =
|
||||||
|
self.query_result_substitution_guess(cause, original_values, query_result);
|
||||||
|
|
||||||
|
let obligations = self
|
||||||
|
.unify_query_result_substitution_guess(
|
||||||
|
cause,
|
||||||
|
param_env,
|
||||||
|
original_values,
|
||||||
|
&result_subst,
|
||||||
|
query_result,
|
||||||
|
)?
|
||||||
|
.into_obligations();
|
||||||
|
|
||||||
|
Ok(InferOk {
|
||||||
|
value: result_subst,
|
||||||
|
obligations,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given the original values and the (canonicalized) result from
|
||||||
|
/// computing a query, returns a **guess** at a substitution that
|
||||||
|
/// can be applied to the query result to convert the result back
|
||||||
|
/// into the original namespace. This is called a **guess**
|
||||||
|
/// because it uses a quick heuristic to find the values for each
|
||||||
|
/// canonical variable; if that quick heuristic fails, then we
|
||||||
|
/// will instantiate fresh inference variables for each canonical
|
||||||
|
/// variable instead. Therefore, the result of this method must be
|
||||||
|
/// properly unified
|
||||||
|
fn query_result_substitution_guess<R>(
|
||||||
|
&self,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
original_values: &CanonicalVarValues<'tcx>,
|
||||||
|
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
|
||||||
|
) -> CanonicalVarValues<'tcx>
|
||||||
|
where
|
||||||
|
R: Debug + TypeFoldable<'tcx>,
|
||||||
|
{
|
||||||
|
debug!(
|
||||||
|
"query_result_substitution_guess(original_values={:#?}, query_result={:#?})",
|
||||||
original_values, query_result,
|
original_values, query_result,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -256,22 +296,37 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unify the original values for the canonical variables in
|
result_subst
|
||||||
// the input with the value found in the query
|
}
|
||||||
// post-substitution. Often, but not always, this is a no-op,
|
|
||||||
// because we already found the mapping in the first step.
|
/// Given a "guess" at the values for the canonical variables in
|
||||||
let obligations = {
|
/// the input, try to unify with the *actual* values found in the
|
||||||
let substituted_values = |index: CanonicalVar| -> Kind<'tcx> {
|
/// query result. Often, but not always, this is a no-op, because
|
||||||
query_result.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
|
/// we already found the mapping in the "guessing" step.
|
||||||
};
|
///
|
||||||
self.unify_canonical_vars(cause, param_env, original_values, substituted_values)?
|
/// See also: `query_result_substitution_guess`
|
||||||
.into_obligations()
|
fn unify_query_result_substitution_guess<R>(
|
||||||
|
&self,
|
||||||
|
cause: &ObligationCause<'tcx>,
|
||||||
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
original_values: &CanonicalVarValues<'tcx>,
|
||||||
|
result_subst: &CanonicalVarValues<'tcx>,
|
||||||
|
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
|
||||||
|
) -> InferResult<'tcx, ()>
|
||||||
|
where
|
||||||
|
R: Debug + TypeFoldable<'tcx>,
|
||||||
|
{
|
||||||
|
// A closure that yields the result value for the given
|
||||||
|
// canonical variable; this is taken from
|
||||||
|
// `query_result.var_values` after applying the substitution
|
||||||
|
// `result_subst`.
|
||||||
|
let substituted_query_result = |index: CanonicalVar| -> Kind<'tcx> {
|
||||||
|
query_result.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(InferOk {
|
// Unify the original value for each variable with the value
|
||||||
value: result_subst,
|
// taken from `query_result` (after applying `result_subst`).
|
||||||
obligations,
|
Ok(self.unify_canonical_vars(cause, param_env, original_values, substituted_query_result)?)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the region constraints resulting from a query into an
|
/// Converts the region constraints resulting from a query into an
|
||||||
|
Loading…
Reference in New Issue
Block a user