1- use std:: cmp:: Ordering ;
2-
31use rustc_type_ir:: data_structures:: { HashMap , ensure_sufficient_stack} ;
42use rustc_type_ir:: inherent:: * ;
53use rustc_type_ir:: solve:: { Goal , QueryInput } ;
@@ -266,11 +264,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
266264 // See the rustc-dev-guide section about how we deal with universes
267265 // during canonicalization in the new solver.
268266 match self . canonicalize_mode {
269- // We try to deduplicate as many query calls as possible and hide
270- // all information which should not matter for the solver.
271- //
272- // For this we compress universes as much as possible.
273- CanonicalizeMode :: Input { .. } => { }
267+ // All placeholders and vars are canonicalized in the root universe.
268+ CanonicalizeMode :: Input { .. } => {
269+ debug_assert ! (
270+ var_kinds. iter( ) . all( |var| var. universe( ) == ty:: UniverseIndex :: ROOT ) ,
271+ "expected all vars to be canonicalized in root universe: {var_kinds:#?}"
272+ ) ;
273+ let var_kinds = self . delegate . cx ( ) . mk_canonical_var_kinds ( & var_kinds) ;
274+ ( ty:: UniverseIndex :: ROOT , var_kinds)
275+ }
274276 // When canonicalizing a response we map a universes already entered
275277 // by the caller to the root universe and only return useful universe
276278 // information for placeholders and inference variables created inside
@@ -288,113 +290,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
288290 . map ( |kind| kind. universe ( ) )
289291 . max ( )
290292 . unwrap_or ( ty:: UniverseIndex :: ROOT ) ;
291-
292293 let var_kinds = self . delegate . cx ( ) . mk_canonical_var_kinds ( & var_kinds) ;
293- return ( max_universe, var_kinds) ;
294+ ( max_universe, var_kinds)
294295 }
295296 }
296-
297- // Given a `var_kinds` with existentials `En` and universals `Un` in
298- // universes `n`, this algorithm compresses them in place so that:
299- //
300- // - the new universe indices are as small as possible
301- // - we create a new universe if we would otherwise
302- // 1. put existentials from a different universe into the same one
303- // 2. put a placeholder in the same universe as an existential which cannot name it
304- //
305- // Let's walk through an example:
306- // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 0
307- // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 0, next_orig_uv: 1
308- // - var_kinds: [E0, U1, E5, U2, E2, E6, U6], curr_compressed_uv: 1, next_orig_uv: 2
309- // - var_kinds: [E0, U1, E5, U1, E1, E6, U6], curr_compressed_uv: 1, next_orig_uv: 5
310- // - var_kinds: [E0, U1, E2, U1, E1, E6, U6], curr_compressed_uv: 2, next_orig_uv: 6
311- // - var_kinds: [E0, U1, E1, U1, E1, E3, U3], curr_compressed_uv: 2, next_orig_uv: -
312- //
313- // This algorithm runs in `O(mn)` where `n` is the number of different universes and
314- // `m` the number of variables. This should be fine as both are expected to be small.
315- let mut curr_compressed_uv = ty:: UniverseIndex :: ROOT ;
316- let mut existential_in_new_uv = None ;
317- let mut next_orig_uv = Some ( ty:: UniverseIndex :: ROOT ) ;
318- while let Some ( orig_uv) = next_orig_uv. take ( ) {
319- let mut update_uv = |var : & mut CanonicalVarKind < I > , orig_uv, is_existential| {
320- let uv = var. universe ( ) ;
321- match uv. cmp ( & orig_uv) {
322- Ordering :: Less => ( ) , // Already updated
323- Ordering :: Equal => {
324- if is_existential {
325- if existential_in_new_uv. is_some_and ( |uv| uv < orig_uv) {
326- // Condition 1.
327- //
328- // We already put an existential from a outer universe
329- // into the current compressed universe, so we need to
330- // create a new one.
331- curr_compressed_uv = curr_compressed_uv. next_universe ( ) ;
332- }
333-
334- // `curr_compressed_uv` will now contain an existential from
335- // `orig_uv`. Trying to canonicalizing an existential from
336- // a higher universe has to therefore use a new compressed
337- // universe.
338- existential_in_new_uv = Some ( orig_uv) ;
339- } else if existential_in_new_uv. is_some ( ) {
340- // Condition 2.
341- //
342- // `var` is a placeholder from a universe which is not nameable
343- // by an existential which we already put into the compressed
344- // universe `curr_compressed_uv`. We therefore have to create a
345- // new universe for `var`.
346- curr_compressed_uv = curr_compressed_uv. next_universe ( ) ;
347- existential_in_new_uv = None ;
348- }
349-
350- * var = var. with_updated_universe ( curr_compressed_uv) ;
351- }
352- Ordering :: Greater => {
353- // We can ignore this variable in this iteration. We only look at
354- // universes which actually occur in the input for performance.
355- //
356- // For this we set `next_orig_uv` to the next smallest, not yet compressed,
357- // universe of the input.
358- if next_orig_uv. is_none_or ( |curr_next_uv| uv. cannot_name ( curr_next_uv) ) {
359- next_orig_uv = Some ( uv) ;
360- }
361- }
362- }
363- } ;
364-
365- // For each universe which occurs in the input, we first iterate over all
366- // placeholders and then over all inference variables.
367- //
368- // Whenever we compress the universe of a placeholder, no existential with
369- // an already compressed universe can name that placeholder.
370- for is_existential in [ false , true ] {
371- for var in var_kinds. iter_mut ( ) {
372- // We simply put all regions from the input into the highest
373- // compressed universe, so we only deal with them at the end.
374- if !var. is_region ( ) {
375- if is_existential == var. is_existential ( ) {
376- update_uv ( var, orig_uv, is_existential)
377- }
378- }
379- }
380- }
381- }
382-
383- // We put all regions into a separate universe.
384- let mut first_region = true ;
385- for var in var_kinds. iter_mut ( ) {
386- if var. is_region ( ) {
387- if first_region {
388- first_region = false ;
389- curr_compressed_uv = curr_compressed_uv. next_universe ( ) ;
390- }
391- debug_assert ! ( var. is_existential( ) ) ;
392- * var = var. with_updated_universe ( curr_compressed_uv) ;
393- }
394- }
395-
396- let var_kinds = self . delegate . cx ( ) . mk_canonical_var_kinds ( & var_kinds) ;
397- ( curr_compressed_uv, var_kinds)
398297 }
399298
400299 fn cached_fold_ty ( & mut self , t : I :: Ty ) -> I :: Ty {
@@ -407,11 +306,18 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
407306 "ty vid should have been resolved fully before canonicalization"
408307 ) ;
409308
410- CanonicalVarKind :: Ty ( CanonicalTyVarKind :: General (
411- self . delegate
412- . universe_of_ty ( vid)
413- . unwrap_or_else ( || panic ! ( "ty var should have been resolved: {t:?}" ) ) ,
414- ) )
309+ match self . canonicalize_mode {
310+ CanonicalizeMode :: Input { .. } => CanonicalVarKind :: Ty (
311+ CanonicalTyVarKind :: General ( ty:: UniverseIndex :: ROOT ) ,
312+ ) ,
313+ CanonicalizeMode :: Response { .. } => {
314+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: General (
315+ self . delegate . universe_of_ty ( vid) . unwrap_or_else ( || {
316+ panic ! ( "ty var should have been resolved: {t:?}" )
317+ } ) ,
318+ ) )
319+ }
320+ }
415321 }
416322 ty:: IntVar ( vid) => {
417323 debug_assert_eq ! (
@@ -435,7 +341,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
435341 } ,
436342 ty:: Placeholder ( placeholder) => match self . canonicalize_mode {
437343 CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderTy (
438- PlaceholderLike :: new_anon ( placeholder . universe ( ) , self . variables . len ( ) . into ( ) ) ,
344+ PlaceholderLike :: new_anon ( ty :: UniverseIndex :: ROOT , self . variables . len ( ) . into ( ) ) ,
439345 ) ,
440346 CanonicalizeMode :: Response { .. } => CanonicalVarKind :: PlaceholderTy ( placeholder) ,
441347 } ,
@@ -588,13 +494,21 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
588494 c,
589495 "const vid should have been resolved fully before canonicalization"
590496 ) ;
591- CanonicalVarKind :: Const ( self . delegate . universe_of_ct ( vid) . unwrap ( ) )
497+
498+ match self . canonicalize_mode {
499+ CanonicalizeMode :: Input { .. } => {
500+ CanonicalVarKind :: Const ( ty:: UniverseIndex :: ROOT )
501+ }
502+ CanonicalizeMode :: Response { .. } => {
503+ CanonicalVarKind :: Const ( self . delegate . universe_of_ct ( vid) . unwrap ( ) )
504+ }
505+ }
592506 }
593507 ty:: InferConst :: Fresh ( _) => todo ! ( ) ,
594508 } ,
595509 ty:: ConstKind :: Placeholder ( placeholder) => match self . canonicalize_mode {
596510 CanonicalizeMode :: Input { .. } => CanonicalVarKind :: PlaceholderConst (
597- PlaceholderLike :: new_anon ( placeholder . universe ( ) , self . variables . len ( ) . into ( ) ) ,
511+ PlaceholderLike :: new_anon ( ty :: UniverseIndex :: ROOT , self . variables . len ( ) . into ( ) ) ,
598512 ) ,
599513 CanonicalizeMode :: Response { .. } => {
600514 CanonicalVarKind :: PlaceholderConst ( placeholder)
0 commit comments