1
- use std::cmp::Ordering;
2
-
3
1
use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
4
2
use rustc_type_ir::inherent::*;
5
3
use rustc_type_ir::solve::{Goal, QueryInput};
@@ -266,11 +264,15 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
266
264
// See the rustc-dev-guide section about how we deal with universes
267
265
// during canonicalization in the new solver.
268
266
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
+ }
274
276
// When canonicalizing a response we map a universes already entered
275
277
// by the caller to the root universe and only return useful universe
276
278
// information for placeholders and inference variables created inside
@@ -288,113 +290,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
288
290
.map(|kind| kind.universe())
289
291
.max()
290
292
.unwrap_or(ty::UniverseIndex::ROOT);
291
-
292
293
let var_kinds = self.delegate.cx().mk_canonical_var_kinds(&var_kinds);
293
- return (max_universe, var_kinds);
294
+ (max_universe, var_kinds)
294
295
}
295
296
}
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)
398
297
}
399
298
400
299
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> {
407
306
"ty vid should have been resolved fully before canonicalization"
408
307
);
409
308
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
+ }
415
321
}
416
322
ty::IntVar(vid) => {
417
323
debug_assert_eq!(
@@ -435,7 +341,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
435
341
},
436
342
ty::Placeholder(placeholder) => match self.canonicalize_mode {
437
343
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()),
439
345
),
440
346
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
441
347
},
@@ -588,13 +494,21 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
588
494
c,
589
495
"const vid should have been resolved fully before canonicalization"
590
496
);
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
+ }
592
506
}
593
507
ty::InferConst::Fresh(_) => todo!(),
594
508
},
595
509
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
596
510
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()),
598
512
),
599
513
CanonicalizeMode::Response { .. } => {
600
514
CanonicalVarKind::PlaceholderConst(placeholder)
0 commit comments