1010//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
1111
1212use std:: iter;
13+ use std:: marker:: PhantomData ;
1314
1415use canonicalizer:: Canonicalizer ;
1516use rustc_index:: IndexVec ;
16- use rustc_type_ir:: error:: TypeError ;
1717use rustc_type_ir:: inherent:: * ;
1818use rustc_type_ir:: relate:: solver_relating:: RelateExt ;
1919use rustc_type_ir:: {
2020 self as ty, Canonical , CanonicalVarKind , CanonicalVarValues , InferCtxtLike , Interner ,
21- TypeFoldable , TypingMode , TypingModeEqWrapper ,
21+ TypeFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitor , TypingMode , TypingModeEqWrapper ,
2222} ;
2323use tracing:: instrument;
2424
@@ -145,12 +145,29 @@ where
145145 // FIXME: Longterm canonical queries should deal with all placeholders
146146 // created inside of the query directly instead of returning them to the
147147 // caller.
148- let prev_universe = delegate. universe ( ) ;
149- let universes_created_in_query = response. max_universe . index ( ) ;
150- for _ in 0 ..universes_created_in_query {
151- delegate. create_next_universe ( ) ;
152- }
148+ let prev_universe = create_universes_for_response ( delegate, response) ;
153149
150+ compute_query_response_instantiation_values_in_universe (
151+ delegate,
152+ original_values,
153+ response,
154+ span,
155+ prev_universe,
156+ )
157+ }
158+
159+ fn compute_query_response_instantiation_values_in_universe < D , I , T > (
160+ delegate : & D ,
161+ original_values : & [ I :: GenericArg ] ,
162+ response : & Canonical < I , T > ,
163+ span : I :: Span ,
164+ prev_universe : ty:: UniverseIndex ,
165+ ) -> CanonicalVarValues < I >
166+ where
167+ D : SolverDelegate < Interner = I > ,
168+ I : Interner ,
169+ T : ResponseT < I > ,
170+ {
154171 let var_values = response. value . var_values ( ) ;
155172 assert_eq ! ( original_values. len( ) , var_values. len( ) ) ;
156173
@@ -234,6 +251,109 @@ where
234251 } )
235252}
236253
254+ fn create_universes_for_response < D , I , T > (
255+ delegate : & D ,
256+ response : & Canonical < I , T > ,
257+ ) -> ty:: UniverseIndex
258+ where
259+ D : SolverDelegate < Interner = I > ,
260+ I : Interner ,
261+ {
262+ let prev_universe = delegate. universe ( ) ;
263+ let universes_created_in_query = response. max_universe . index ( ) ;
264+ for _ in 0 ..universes_created_in_query {
265+ delegate. create_next_universe ( ) ;
266+ }
267+ prev_universe
268+ }
269+
270+ fn max_input_universe_for_replay < D , I > (
271+ delegate : & D ,
272+ orig_values : & [ I :: GenericArg ] ,
273+ ) -> ty:: UniverseIndex
274+ where
275+ D : SolverDelegate < Interner = I > ,
276+ I : Interner ,
277+ {
278+ struct MaxUniverseVisitor < ' a , D , I > {
279+ delegate : & ' a D ,
280+ max_universe : ty:: UniverseIndex ,
281+ _interner : PhantomData < I > ,
282+ }
283+
284+ impl < D , I > TypeVisitor < I > for MaxUniverseVisitor < ' _ , D , I >
285+ where
286+ D : SolverDelegate < Interner = I > ,
287+ I : Interner ,
288+ {
289+ type Result = ( ) ;
290+
291+ fn visit_ty ( & mut self , t : I :: Ty ) -> Self :: Result {
292+ match t. kind ( ) {
293+ ty:: Placeholder ( placeholder) => {
294+ self . max_universe = self . max_universe . max ( placeholder. universe ( ) ) ;
295+ }
296+ ty:: Infer ( ty:: TyVar ( vid) ) => {
297+ if let Some ( universe) = self . delegate . universe_of_ty ( vid) {
298+ self . max_universe = self . max_universe . max ( universe) ;
299+ }
300+ }
301+ _ => { }
302+ }
303+ t. super_visit_with ( self )
304+ }
305+
306+ fn visit_region ( & mut self , r : I :: Region ) -> Self :: Result {
307+ match r. kind ( ) {
308+ ty:: RePlaceholder ( placeholder) => {
309+ self . max_universe = self . max_universe . max ( placeholder. universe ( ) ) ;
310+ }
311+ ty:: ReVar ( vid) => {
312+ if let Some ( universe) = self . delegate . universe_of_lt ( vid) {
313+ self . max_universe = self . max_universe . max ( universe) ;
314+ }
315+ }
316+ _ => { }
317+ }
318+ }
319+
320+ fn visit_const ( & mut self , c : I :: Const ) -> Self :: Result {
321+ match c. kind ( ) {
322+ ty:: ConstKind :: Placeholder ( placeholder) => {
323+ self . max_universe = self . max_universe . max ( placeholder. universe ( ) ) ;
324+ }
325+ ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( vid) ) => {
326+ if let Some ( universe) = self . delegate . universe_of_ct ( vid) {
327+ self . max_universe = self . max_universe . max ( universe) ;
328+ }
329+ }
330+ _ => { }
331+ }
332+ c. super_visit_with ( self )
333+ }
334+ }
335+
336+ let mut visitor = MaxUniverseVisitor {
337+ delegate,
338+ max_universe : ty:: UniverseIndex :: ROOT ,
339+ _interner : PhantomData ,
340+ } ;
341+ for value in orig_values {
342+ value. visit_with ( & mut visitor) ;
343+ }
344+ visitor. max_universe
345+ }
346+
347+ fn ensure_universes_through < D , I > ( delegate : & D , max_universe : ty:: UniverseIndex )
348+ where
349+ D : SolverDelegate < Interner = I > ,
350+ I : Interner ,
351+ {
352+ while delegate. universe ( ) < max_universe {
353+ delegate. create_next_universe ( ) ;
354+ }
355+ }
356+
237357/// Unify the `original_values` with the `var_values` returned by the canonical query..
238358///
239359/// This assumes that this unification will always succeed. This is the case when
@@ -247,39 +367,23 @@ where
247367/// from the solver we assume that the solver correctly handled aliases and therefore
248368/// always relate them structurally here.
249369#[ instrument( level = "trace" , skip( delegate) ) ]
250- fn try_unify_query_var_values < D , I > (
370+ fn unify_query_var_values < D , I > (
251371 delegate : & D ,
252372 param_env : I :: ParamEnv ,
253373 original_values : & [ I :: GenericArg ] ,
254374 var_values : CanonicalVarValues < I > ,
255375 span : I :: Span ,
256- ) -> Result < ( ) , TypeError < I > >
257- where
376+ ) where
258377 D : SolverDelegate < Interner = I > ,
259378 I : Interner ,
260379{
261380 assert_eq ! ( original_values. len( ) , var_values. len( ) ) ;
262381
263382 for ( & orig, response) in iter:: zip ( original_values, var_values. var_values . iter ( ) ) {
264- let goals = delegate. eq_structurally_relating_aliases ( param_env, orig, response, span) ?;
383+ let goals =
384+ delegate. eq_structurally_relating_aliases ( param_env, orig, response, span) . unwrap ( ) ;
265385 assert ! ( goals. is_empty( ) ) ;
266386 }
267-
268- Ok ( ( ) )
269- }
270-
271- #[ instrument( level = "trace" , skip( delegate) ) ]
272- fn unify_query_var_values < D , I > (
273- delegate : & D ,
274- param_env : I :: ParamEnv ,
275- original_values : & [ I :: GenericArg ] ,
276- var_values : CanonicalVarValues < I > ,
277- span : I :: Span ,
278- ) where
279- D : SolverDelegate < Interner = I > ,
280- I : Interner ,
281- {
282- try_unify_query_var_values ( delegate, param_env, original_values, var_values, span) . unwrap ( ) ;
283387}
284388
285389fn register_region_constraints < D , I > (
@@ -357,43 +461,34 @@ pub fn instantiate_canonical_state<D, I, T>(
357461 orig_values : & mut Vec < I :: GenericArg > ,
358462 state : inspect:: CanonicalState < I , T > ,
359463) -> T
360- where
361- D : SolverDelegate < Interner = I > ,
362- I : Interner ,
363- T : TypeFoldable < I > ,
364- {
365- try_instantiate_canonical_state ( delegate, span, param_env, orig_values, state) . unwrap ( )
366- }
367-
368- // FIXME: needs to be pub to be accessed by downstream
369- // `rustc_trait_selection::solve::inspect::analyse`.
370- pub fn try_instantiate_canonical_state < D , I , T > (
371- delegate : & D ,
372- span : I :: Span ,
373- param_env : I :: ParamEnv ,
374- orig_values : & mut Vec < I :: GenericArg > ,
375- state : inspect:: CanonicalState < I , T > ,
376- ) -> Result < T , TypeError < I > >
377464where
378465 D : SolverDelegate < Interner = I > ,
379466 I : Interner ,
380467 T : TypeFoldable < I > ,
381468{
382469 // In case any fresh inference variables have been created between `state`
383470 // and the previous instantiation, extend `orig_values` for it.
471+ let prev_universe = max_input_universe_for_replay ( delegate, orig_values) ;
472+ let max_universe = prev_universe + state. max_universe . index ( ) ;
473+ ensure_universes_through ( delegate, max_universe) ;
384474 orig_values. extend (
385475 state. value . var_values . var_values . as_slice ( ) [ orig_values. len ( ) ..]
386476 . iter ( )
387- . map ( |& arg| delegate. fresh_var_for_kind_with_span ( arg, span) ) ,
477+ . map ( |& arg| delegate. fresh_var_for_kind_in_universe ( arg, span, max_universe ) ) ,
388478 ) ;
389479
390- let instantiation =
391- compute_query_response_instantiation_values ( delegate, orig_values, & state, span) ;
480+ let instantiation = compute_query_response_instantiation_values_in_universe (
481+ delegate,
482+ orig_values,
483+ & state,
484+ span,
485+ prev_universe,
486+ ) ;
392487
393488 let inspect:: State { var_values, data } = delegate. instantiate_canonical ( state, instantiation) ;
394489
395- try_unify_query_var_values ( delegate, param_env, orig_values, var_values, span) ? ;
396- Ok ( data)
490+ unify_query_var_values ( delegate, param_env, orig_values, var_values, span) ;
491+ data
397492}
398493
399494pub fn response_no_constraints_raw < I : Interner > (
0 commit comments