1010//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
1111use super :: { CanonicalInput , Certainty , EvalCtxt , Goal } ;
1212use 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+ } ;
1416use rustc_data_structures:: fx:: FxHashSet ;
1517use rustc_index:: IndexVec ;
1618use rustc_infer:: infer:: canonical:: query_response:: make_query_region_constraints;
1719use rustc_infer:: infer:: canonical:: CanonicalVarValues ;
1820use 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 ;
2023use rustc_middle:: traits:: query:: NoSolution ;
2124use rustc_middle:: traits:: solve:: {
2225 ExternalConstraintsData , MaybeCause , PredefinedOpaquesData , QueryInput ,
2326} ;
27+ use rustc_middle:: traits:: ObligationCause ;
2428use rustc_middle:: ty:: {
2529 self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable ,
2630 TypeVisitableExt ,
@@ -29,6 +33,22 @@ use rustc_span::DUMMY_SP;
2933use std:: iter;
3034use std:: ops:: Deref ;
3135
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+
3252impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
3353 /// Canonicalizes the goal remembering the original values
3454 /// for each bound variable.
@@ -188,12 +208,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
188208 original_values : Vec < ty:: GenericArg < ' tcx > > ,
189209 response : CanonicalResponse < ' tcx > ,
190210 ) -> 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) ;
192213
193214 let Response { var_values, external_constraints, certainty } =
194215 response. substitute ( self . tcx ( ) , & substitution) ;
195216
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) ?;
197219
198220 let ExternalConstraintsData { region_constraints, opaque_types } =
199221 external_constraints. deref ( ) ;
@@ -206,21 +228,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
206228 /// This returns the substitutions to instantiate the bound variables of
207229 /// the canonical response. This depends on the `original_values` for the
208230 /// bound variables.
209- fn compute_query_response_substitution (
210- & self ,
231+ fn compute_query_response_substitution < T : ResponseT < ' tcx > > (
232+ infcx : & InferCtxt < ' tcx > ,
211233 original_values : & [ ty:: GenericArg < ' tcx > ] ,
212- response : & CanonicalResponse < ' tcx > ,
234+ response : & Canonical < ' tcx , T > ,
213235 ) -> CanonicalVarValues < ' tcx > {
214236 // FIXME: Longterm canonical queries should deal with all placeholders
215237 // created inside of the query directly instead of returning them to the
216238 // caller.
217- let prev_universe = self . infcx . universe ( ) ;
239+ let prev_universe = infcx. universe ( ) ;
218240 let universes_created_in_query = response. max_universe . index ( ) ;
219241 for _ in 0 ..universes_created_in_query {
220- self . infcx . create_next_universe ( ) ;
242+ infcx. create_next_universe ( ) ;
221243 }
222244
223- let var_values = response. value . var_values ;
245+ let var_values = response. value . var_values ( ) ;
224246 assert_eq ! ( original_values. len( ) , var_values. len( ) ) ;
225247
226248 // If the query did not make progress with constraining inference variables,
@@ -254,13 +276,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
254276 }
255277 }
256278
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 (
258280 |( index, info) | {
259281 if info. universe ( ) != ty:: UniverseIndex :: ROOT {
260282 // A variable from inside a binder of the query. While ideally these shouldn't
261283 // exist at all (see the FIXME at the start of this method), we have to deal with
262284 // them for now.
263- self . infcx . instantiate_canonical_var ( DUMMY_SP , info, |idx| {
285+ infcx. instantiate_canonical_var ( DUMMY_SP , info, |idx| {
264286 ty:: UniverseIndex :: from ( prev_universe. index ( ) + idx. index ( ) )
265287 } )
266288 } else if info. is_existential ( ) {
@@ -274,7 +296,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
274296 if let Some ( v) = opt_values[ BoundVar :: from_usize ( index) ] {
275297 v
276298 } else {
277- self . infcx . instantiate_canonical_var ( DUMMY_SP , info, |_| prev_universe)
299+ infcx. instantiate_canonical_var ( DUMMY_SP , info, |_| prev_universe)
278300 }
279301 } else {
280302 // For placeholders which were already part of the input, we simply map this
@@ -287,9 +309,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
287309 CanonicalVarValues { var_values }
288310 }
289311
290- #[ instrument( level = "debug" , skip( self , param_env) , ret) ]
312+ #[ instrument( level = "debug" , skip( infcx , param_env) , ret) ]
291313 fn unify_query_var_values (
292- & self ,
314+ infcx : & InferCtxt < ' tcx > ,
293315 param_env : ty:: ParamEnv < ' tcx > ,
294316 original_values : & [ ty:: GenericArg < ' tcx > ] ,
295317 var_values : CanonicalVarValues < ' tcx > ,
@@ -298,7 +320,18 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
298320
299321 let mut nested_goals = vec ! [ ] ;
300322 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+ ) ;
302335 }
303336
304337 Ok ( nested_goals)
@@ -403,3 +436,35 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerResolver<'_, 'tcx> {
403436 }
404437 }
405438}
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