10
10
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
11
11
use super :: { CanonicalInput , Certainty , EvalCtxt , Goal } ;
12
12
use crate :: solve:: canonicalize:: { CanonicalizeMode , Canonicalizer } ;
13
- use crate :: solve:: { response_no_constraints_raw, CanonicalResponse , QueryResult , Response } ;
13
+ use crate :: solve:: {
14
+ inspect, response_no_constraints_raw, CanonicalResponse , QueryResult , Response ,
15
+ } ;
14
16
use rustc_data_structures:: fx:: FxHashSet ;
15
17
use rustc_index:: IndexVec ;
16
18
use rustc_infer:: infer:: canonical:: query_response:: make_query_region_constraints;
17
19
use rustc_infer:: infer:: canonical:: CanonicalVarValues ;
18
20
use rustc_infer:: infer:: canonical:: { CanonicalExt , QueryRegionConstraints } ;
19
- use rustc_infer:: infer:: InferCtxt ;
21
+ use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
22
+ use rustc_middle:: infer:: canonical:: Canonical ;
20
23
use rustc_middle:: traits:: query:: NoSolution ;
21
24
use rustc_middle:: traits:: solve:: {
22
25
ExternalConstraintsData , MaybeCause , PredefinedOpaquesData , QueryInput ,
23
26
} ;
27
+ use rustc_middle:: traits:: ObligationCause ;
24
28
use rustc_middle:: ty:: {
25
29
self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable ,
26
30
TypeVisitableExt ,
@@ -29,6 +33,22 @@ use rustc_span::DUMMY_SP;
29
33
use std:: iter;
30
34
use std:: ops:: Deref ;
31
35
36
+ trait ResponseT < ' tcx > {
37
+ fn var_values ( & self ) -> CanonicalVarValues < ' tcx > ;
38
+ }
39
+
40
+ impl < ' tcx > ResponseT < ' tcx > for Response < ' tcx > {
41
+ fn var_values ( & self ) -> CanonicalVarValues < ' tcx > {
42
+ self . var_values
43
+ }
44
+ }
45
+
46
+ impl < ' tcx , T > ResponseT < ' tcx > for inspect:: State < ' tcx , T > {
47
+ fn var_values ( & self ) -> CanonicalVarValues < ' tcx > {
48
+ self . var_values
49
+ }
50
+ }
51
+
32
52
impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
33
53
/// Canonicalizes the goal remembering the original values
34
54
/// for each bound variable.
@@ -188,12 +208,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
188
208
original_values : Vec < ty:: GenericArg < ' tcx > > ,
189
209
response : CanonicalResponse < ' tcx > ,
190
210
) -> Result < ( Certainty , Vec < Goal < ' tcx , ty:: Predicate < ' tcx > > > ) , NoSolution > {
191
- let substitution = self . compute_query_response_substitution ( & original_values, & response) ;
211
+ let substitution =
212
+ Self :: compute_query_response_substitution ( self . infcx , & original_values, & response) ;
192
213
193
214
let Response { var_values, external_constraints, certainty } =
194
215
response. substitute ( self . tcx ( ) , & substitution) ;
195
216
196
- let nested_goals = self . unify_query_var_values ( param_env, & original_values, var_values) ?;
217
+ let nested_goals =
218
+ Self :: unify_query_var_values ( self . infcx , param_env, & original_values, var_values) ?;
197
219
198
220
let ExternalConstraintsData { region_constraints, opaque_types } =
199
221
external_constraints. deref ( ) ;
@@ -206,21 +228,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
206
228
/// This returns the substitutions to instantiate the bound variables of
207
229
/// the canonical response. This depends on the `original_values` for the
208
230
/// bound variables.
209
- fn compute_query_response_substitution (
210
- & self ,
231
+ fn compute_query_response_substitution < T : ResponseT < ' tcx > > (
232
+ infcx : & InferCtxt < ' tcx > ,
211
233
original_values : & [ ty:: GenericArg < ' tcx > ] ,
212
- response : & CanonicalResponse < ' tcx > ,
234
+ response : & Canonical < ' tcx , T > ,
213
235
) -> CanonicalVarValues < ' tcx > {
214
236
// FIXME: Longterm canonical queries should deal with all placeholders
215
237
// created inside of the query directly instead of returning them to the
216
238
// caller.
217
- let prev_universe = self . infcx . universe ( ) ;
239
+ let prev_universe = infcx. universe ( ) ;
218
240
let universes_created_in_query = response. max_universe . index ( ) ;
219
241
for _ in 0 ..universes_created_in_query {
220
- self . infcx . create_next_universe ( ) ;
242
+ infcx. create_next_universe ( ) ;
221
243
}
222
244
223
- let var_values = response. value . var_values ;
245
+ let var_values = response. value . var_values ( ) ;
224
246
assert_eq ! ( original_values. len( ) , var_values. len( ) ) ;
225
247
226
248
// If the query did not make progress with constraining inference variables,
@@ -254,13 +276,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
254
276
}
255
277
}
256
278
257
- let var_values = self . tcx ( ) . mk_args_from_iter ( response. variables . iter ( ) . enumerate ( ) . map (
279
+ let var_values = infcx . tcx . mk_args_from_iter ( response. variables . iter ( ) . enumerate ( ) . map (
258
280
|( index, info) | {
259
281
if info. universe ( ) != ty:: UniverseIndex :: ROOT {
260
282
// A variable from inside a binder of the query. While ideally these shouldn't
261
283
// exist at all (see the FIXME at the start of this method), we have to deal with
262
284
// them for now.
263
- self . infcx . instantiate_canonical_var ( DUMMY_SP , info, |idx| {
285
+ infcx. instantiate_canonical_var ( DUMMY_SP , info, |idx| {
264
286
ty:: UniverseIndex :: from ( prev_universe. index ( ) + idx. index ( ) )
265
287
} )
266
288
} else if info. is_existential ( ) {
@@ -274,7 +296,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
274
296
if let Some ( v) = opt_values[ BoundVar :: from_usize ( index) ] {
275
297
v
276
298
} else {
277
- self . infcx . instantiate_canonical_var ( DUMMY_SP , info, |_| prev_universe)
299
+ infcx. instantiate_canonical_var ( DUMMY_SP , info, |_| prev_universe)
278
300
}
279
301
} else {
280
302
// For placeholders which were already part of the input, we simply map this
@@ -287,9 +309,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
287
309
CanonicalVarValues { var_values }
288
310
}
289
311
290
- #[ instrument( level = "debug" , skip( self , param_env) , ret) ]
312
+ #[ instrument( level = "debug" , skip( infcx , param_env) , ret) ]
291
313
fn unify_query_var_values (
292
- & self ,
314
+ infcx : & InferCtxt < ' tcx > ,
293
315
param_env : ty:: ParamEnv < ' tcx > ,
294
316
original_values : & [ ty:: GenericArg < ' tcx > ] ,
295
317
var_values : CanonicalVarValues < ' tcx > ,
@@ -298,7 +320,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
298
320
299
321
let mut nested_goals = vec ! [ ] ;
300
322
for ( & orig, response) in iter:: zip ( original_values, var_values. var_values ) {
301
- nested_goals. extend ( self . eq_and_get_goals ( param_env, orig, response) ?) ;
323
+ nested_goals. extend (
324
+ infcx
325
+ . at ( & ObligationCause :: dummy ( ) , param_env)
326
+ . eq ( DefineOpaqueTypes :: No , orig, response)
327
+ . map ( |InferOk { value : ( ) , obligations } | {
328
+ obligations. into_iter ( ) . map ( |o| Goal :: from ( o) )
329
+ } )
330
+ . map_err ( |e| {
331
+ debug ! ( ?e, "failed to equate" ) ;
332
+ NoSolution
333
+ } ) ?,
334
+ ) ;
302
335
}
303
336
304
337
Ok ( nested_goals)
@@ -403,3 +436,35 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
403
436
}
404
437
}
405
438
}
439
+
440
+ impl < ' tcx > inspect:: ProofTreeBuilder < ' tcx > {
441
+ pub fn make_canonical_state < T : TypeFoldable < TyCtxt < ' tcx > > > (
442
+ ecx : & EvalCtxt < ' _ , ' tcx > ,
443
+ data : T ,
444
+ ) -> inspect:: CanonicalState < ' tcx , T > {
445
+ let state = inspect:: State { var_values : ecx. var_values , data } ;
446
+ let state = state. fold_with ( & mut EagerResolver { infcx : ecx. infcx } ) ;
447
+ Canonicalizer :: canonicalize (
448
+ ecx. infcx ,
449
+ CanonicalizeMode :: Response { max_input_universe : ecx. max_input_universe } ,
450
+ & mut vec ! [ ] ,
451
+ state,
452
+ )
453
+ }
454
+
455
+ pub fn instantiate_canonical_state < T : TypeFoldable < TyCtxt < ' tcx > > > (
456
+ infcx : & InferCtxt < ' tcx > ,
457
+ param_env : ty:: ParamEnv < ' tcx > ,
458
+ original_values : & [ ty:: GenericArg < ' tcx > ] ,
459
+ state : inspect:: CanonicalState < ' tcx , T > ,
460
+ ) -> Result < ( Vec < Goal < ' tcx , ty:: Predicate < ' tcx > > > , T ) , NoSolution > {
461
+ let substitution =
462
+ EvalCtxt :: compute_query_response_substitution ( infcx, original_values, & state) ;
463
+
464
+ let inspect:: State { var_values, data } = state. substitute ( infcx. tcx , & substitution) ;
465
+
466
+ let nested_goals =
467
+ EvalCtxt :: unify_query_var_values ( infcx, param_env, original_values, var_values) ?;
468
+ Ok ( ( nested_goals, data) )
469
+ }
470
+ }
0 commit comments