Skip to content

Commit 2b634bd

Browse files
committed
extract more helpers from instantiating query result
1 parent 89bcc9f commit 2b634bd

File tree

1 file changed

+79
-24
lines changed

1 file changed

+79
-24
lines changed

src/librustc/infer/canonical/query_result.rs

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
2020
use infer::canonical::substitute::substitute_value;
2121
use infer::canonical::{
22-
Canonical, CanonicalVarValues, CanonicalizedQueryResult, Certainty,
23-
QueryRegionConstraint, QueryResult,
22+
Canonical, CanonicalVarValues, CanonicalizedQueryResult, Certainty, QueryRegionConstraint,
23+
QueryResult,
2424
};
2525
use infer::region_constraints::{Constraint, RegionConstraintData};
2626
use infer::{InferCtxt, InferOk, InferResult, RegionObligation};
@@ -155,12 +155,10 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
155155
where
156156
R: Debug + TypeFoldable<'tcx>,
157157
{
158-
let InferOk { value: result_subst, mut obligations } = self.query_result_substitution(
159-
cause,
160-
param_env,
161-
original_values,
162-
query_result,
163-
)?;
158+
let InferOk {
159+
value: result_subst,
160+
mut obligations,
161+
} = self.query_result_substitution(cause, param_env, original_values, query_result)?;
164162

165163
obligations.extend(self.query_region_constraints_into_obligations(
166164
cause,
@@ -188,7 +186,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
188186
/// example) we are doing lazy normalization and the value
189187
/// assigned to a type variable is unified with an unnormalized
190188
/// projection.
191-
pub fn query_result_substitution<R>(
189+
fn query_result_substitution<R>(
192190
&self,
193191
cause: &ObligationCause<'tcx>,
194192
param_env: ty::ParamEnv<'tcx>,
@@ -199,7 +197,49 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
199197
R: Debug + TypeFoldable<'tcx>,
200198
{
201199
debug!(
202-
"instantiate_query_result(original_values={:#?}, query_result={:#?})",
200+
"query_result_substitution(original_values={:#?}, query_result={:#?})",
201+
original_values, query_result,
202+
);
203+
204+
let result_subst =
205+
self.query_result_substitution_guess(cause, original_values, query_result);
206+
207+
let obligations = self
208+
.unify_query_result_substitution_guess(
209+
cause,
210+
param_env,
211+
original_values,
212+
&result_subst,
213+
query_result,
214+
)?
215+
.into_obligations();
216+
217+
Ok(InferOk {
218+
value: result_subst,
219+
obligations,
220+
})
221+
}
222+
223+
/// Given the original values and the (canonicalized) result from
224+
/// computing a query, returns a **guess** at a substitution that
225+
/// can be applied to the query result to convert the result back
226+
/// into the original namespace. This is called a **guess**
227+
/// because it uses a quick heuristic to find the values for each
228+
/// canonical variable; if that quick heuristic fails, then we
229+
/// will instantiate fresh inference variables for each canonical
230+
/// variable instead. Therefore, the result of this method must be
231+
/// properly unified
232+
fn query_result_substitution_guess<R>(
233+
&self,
234+
cause: &ObligationCause<'tcx>,
235+
original_values: &CanonicalVarValues<'tcx>,
236+
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
237+
) -> CanonicalVarValues<'tcx>
238+
where
239+
R: Debug + TypeFoldable<'tcx>,
240+
{
241+
debug!(
242+
"query_result_substitution_guess(original_values={:#?}, query_result={:#?})",
203243
original_values, query_result,
204244
);
205245

@@ -256,22 +296,37 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
256296
.collect(),
257297
};
258298

259-
// Unify the original values for the canonical variables in
260-
// the input with the value found in the query
261-
// post-substitution. Often, but not always, this is a no-op,
262-
// because we already found the mapping in the first step.
263-
let obligations = {
264-
let substituted_values = |index: CanonicalVar| -> Kind<'tcx> {
265-
query_result.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
266-
};
267-
self.unify_canonical_vars(cause, param_env, original_values, substituted_values)?
268-
.into_obligations()
299+
result_subst
300+
}
301+
302+
/// Given a "guess" at the values for the canonical variables in
303+
/// the input, try to unify with the *actual* values found in the
304+
/// query result. Often, but not always, this is a no-op, because
305+
/// we already found the mapping in the "guessing" step.
306+
///
307+
/// See also: `query_result_substitution_guess`
308+
fn unify_query_result_substitution_guess<R>(
309+
&self,
310+
cause: &ObligationCause<'tcx>,
311+
param_env: ty::ParamEnv<'tcx>,
312+
original_values: &CanonicalVarValues<'tcx>,
313+
result_subst: &CanonicalVarValues<'tcx>,
314+
query_result: &Canonical<'tcx, QueryResult<'tcx, R>>,
315+
) -> InferResult<'tcx, ()>
316+
where
317+
R: Debug + TypeFoldable<'tcx>,
318+
{
319+
// A closure that yields the result value for the given
320+
// canonical variable; this is taken from
321+
// `query_result.var_values` after applying the substitution
322+
// `result_subst`.
323+
let substituted_query_result = |index: CanonicalVar| -> Kind<'tcx> {
324+
query_result.substitute_projected(self.tcx, &result_subst, |v| &v.var_values[index])
269325
};
270326

271-
Ok(InferOk {
272-
value: result_subst,
273-
obligations,
274-
})
327+
// Unify the original value for each variable with the value
328+
// taken from `query_result` (after applying `result_subst`).
329+
Ok(self.unify_canonical_vars(cause, param_env, original_values, substituted_query_result)?)
275330
}
276331

277332
/// Converts the region constraints resulting from a query into an

0 commit comments

Comments
 (0)