19
19
20
20
use infer:: canonical:: substitute:: substitute_value;
21
21
use infer:: canonical:: {
22
- Canonical , CanonicalVarValues , CanonicalizedQueryResult , Certainty ,
23
- QueryRegionConstraint , QueryResult ,
22
+ Canonical , CanonicalVarValues , CanonicalizedQueryResult , Certainty , QueryRegionConstraint ,
23
+ QueryResult ,
24
24
} ;
25
25
use infer:: region_constraints:: { Constraint , RegionConstraintData } ;
26
26
use infer:: { InferCtxt , InferOk , InferResult , RegionObligation } ;
@@ -155,12 +155,10 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
155
155
where
156
156
R : Debug + TypeFoldable < ' tcx > ,
157
157
{
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) ?;
164
162
165
163
obligations. extend ( self . query_region_constraints_into_obligations (
166
164
cause,
@@ -188,7 +186,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
188
186
/// example) we are doing lazy normalization and the value
189
187
/// assigned to a type variable is unified with an unnormalized
190
188
/// projection.
191
- pub fn query_result_substitution < R > (
189
+ fn query_result_substitution < R > (
192
190
& self ,
193
191
cause : & ObligationCause < ' tcx > ,
194
192
param_env : ty:: ParamEnv < ' tcx > ,
@@ -199,7 +197,49 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
199
197
R : Debug + TypeFoldable < ' tcx > ,
200
198
{
201
199
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={:#?})" ,
203
243
original_values, query_result,
204
244
) ;
205
245
@@ -256,22 +296,37 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
256
296
. collect ( ) ,
257
297
} ;
258
298
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] )
269
325
} ;
270
326
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) ?)
275
330
}
276
331
277
332
/// Converts the region constraints resulting from a query into an
0 commit comments