Skip to content

Commit 03d5f39

Browse files
committed
add universe assert in instantiation
1 parent c3d4ba7 commit 03d5f39

3 files changed

Lines changed: 69 additions & 39 deletions

File tree

compiler/rustc_infer/src/infer/context.rs

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -255,21 +255,13 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
255255
}
256256

257257
fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: Ty<'tcx>) {
258-
let ty = ty.fold_with(&mut LowerUniverseFolder {
259-
infcx: self,
260-
for_universe: self.try_resolve_ty_var(vid).unwrap_err(),
261-
cache: Default::default(),
262-
});
258+
let ty = lower_universe(self, self.try_resolve_ty_var(vid).unwrap_err(), ty);
263259

264260
self.inner.borrow_mut().type_variables().instantiate(vid, ty);
265261
}
266262

267263
fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: ty::Const<'tcx>) {
268-
let ct = ct.fold_with(&mut LowerUniverseFolder {
269-
infcx: self,
270-
for_universe: self.try_resolve_const_var(vid).unwrap_err(),
271-
cache: Default::default(),
272-
});
264+
let ct = lower_universe(self, self.try_resolve_const_var(vid).unwrap_err(), ct);
273265

274266
self.inner
275267
.borrow_mut()
@@ -438,6 +430,33 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
438430
}
439431
}
440432

433+
fn lower_universe<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Copy>(
434+
infcx: &InferCtxt<'tcx>,
435+
for_universe: ty::UniverseIndex,
436+
value: T,
437+
) -> T {
438+
let value = value.fold_with(&mut LowerUniverseFolder {
439+
infcx,
440+
for_universe,
441+
cache: Default::default(),
442+
});
443+
444+
// This assertion is needed because we don't lower the universes of placeholders
445+
// in the folder.
446+
#[cfg(debug_assertions)]
447+
{
448+
let value_universe = ty::max_universe(infcx, value);
449+
assert!(
450+
for_universe.can_name(value_universe),
451+
"variable in universe {:?} can't name value in universe {:?}",
452+
for_universe,
453+
value_universe,
454+
);
455+
}
456+
457+
value
458+
}
459+
441460
/// Canonicalizing inputs puts all inference variables and placeholders
442461
/// into the root universe.
443462
///
@@ -487,15 +506,6 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for LowerUniverseFolder<'a, 'tcx> {
487506
}
488507
}
489508
}
490-
ty::Placeholder(p) => {
491-
debug_assert!(
492-
self.for_universe.can_name(p.universe),
493-
"variable in universe {:?} can't name type in universe {:?}",
494-
self.for_universe,
495-
p.universe
496-
);
497-
t
498-
}
499509
_ => t.super_fold_with(self),
500510
};
501511

@@ -532,15 +542,6 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for LowerUniverseFolder<'a, 'tcx> {
532542
ty::Const::new_var(self.cx(), new_var_id)
533543
}
534544
}
535-
ty::ConstKind::Placeholder(p) => {
536-
debug_assert!(
537-
self.for_universe.can_name(p.universe),
538-
"variable in universe {:?} can't name const in universe {:?}",
539-
self.for_universe,
540-
p.universe
541-
);
542-
c
543-
}
544545
_ => c.super_fold_with(self),
545546
}
546547
}

compiler/rustc_infer/src/infer/relate/generalize.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,24 @@ impl<'tcx> InferCtxt<'tcx> {
297297
if let Some(r) = r.ty_vid() {
298298
self.inner.borrow_mut().type_variables().equate(l, r)
299299
} else {
300+
// Ideally, we put this assert into `type_variables().instantiate()`.
301+
// But we can't pass the infcx into it as the infcx is already
302+
// mutably borrowed.
303+
debug_assert!(
304+
self.try_resolve_ty_var(l).unwrap_err().can_name(ty::max_universe(self, r))
305+
);
300306
self.inner.borrow_mut().type_variables().instantiate(l, r)
301307
}
302308
}
303309
(TermVid::Const(l), ty::TermKind::Const(r)) => {
304310
if let Some(r) = r.ct_vid() {
305311
self.inner.borrow_mut().const_unification_table().union(l, r)
306312
} else {
313+
debug_assert!(
314+
self.try_resolve_const_var(l)
315+
.unwrap_err()
316+
.can_name(ty::max_universe(self, r))
317+
);
307318
self.inner
308319
.borrow_mut()
309320
.const_unification_table()

compiler/rustc_type_ir/src/universe.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use tracing::{debug, instrument};
22

3+
use crate::data_structures::HashSet;
34
use crate::inherent::*;
45
use crate::visit::TypeVisitableExt;
56
use crate::{
@@ -49,37 +50,48 @@ fn max_universe_inner<
4950
infcx: &Infcx,
5051
t: T,
5152
) -> UniverseIndex {
52-
if !MaxUniverse::<Infcx, VISIT_PLACEHOLDER, VISIT_INFER>::needs_visit(&t) {
53+
if !MaxUniverse::<Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>::needs_visit(&t) {
5354
return UniverseIndex::ROOT;
5455
}
5556

56-
let mut visitor = MaxUniverse::<_, VISIT_PLACEHOLDER, VISIT_INFER>::new(infcx);
57-
// FIXME: make this a debug_assert and let callers resolve vars if there's
58-
// perf win here.
57+
let mut visitor = MaxUniverse::<_, _, VISIT_PLACEHOLDER, VISIT_INFER>::new(infcx);
58+
// FIXME: make this a debug_assert and let callers resolve vars. Then the input only needs to
59+
// be `TypeVisitable`.
5960
let t = infcx.resolve_vars_if_possible(t);
6061
t.visit_with(&mut visitor);
6162
visitor.max_universe()
6263
}
6364

64-
struct MaxUniverse<'a, Infcx: InferCtxtLike, const VISIT_PLACEHOLDER: bool, const VISIT_INFER: bool>
65-
{
65+
struct MaxUniverse<
66+
'a,
67+
Infcx: InferCtxtLike<Interner = I>,
68+
I: Interner,
69+
const VISIT_PLACEHOLDER: bool,
70+
const VISIT_INFER: bool,
71+
> {
6672
max_universe: UniverseIndex,
6773
infcx: &'a Infcx,
74+
cache: HashSet<I::Ty>,
6875
}
6976

70-
impl<'a, Infcx: InferCtxtLike, const VISIT_PLACEHOLDER: bool, const VISIT_INFER: bool>
71-
MaxUniverse<'a, Infcx, VISIT_PLACEHOLDER, VISIT_INFER>
77+
impl<
78+
'a,
79+
Infcx: InferCtxtLike<Interner = I>,
80+
I: Interner,
81+
const VISIT_PLACEHOLDER: bool,
82+
const VISIT_INFER: bool,
83+
> MaxUniverse<'a, Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>
7284
{
7385
fn new(infcx: &'a Infcx) -> Self {
74-
MaxUniverse { infcx, max_universe: UniverseIndex::ROOT }
86+
MaxUniverse { infcx, max_universe: UniverseIndex::ROOT, cache: Default::default() }
7587
}
7688

7789
fn max_universe(self) -> UniverseIndex {
7890
self.max_universe
7991
}
8092

8193
#[instrument(ret, level = "debug")]
82-
fn needs_visit<T: TypeVisitable<I>, I: Interner>(t: &T) -> bool {
94+
fn needs_visit<T: TypeVisitable<I>>(t: &T) -> bool {
8395
(VISIT_PLACEHOLDER && t.has_placeholders()) || (VISIT_INFER && t.has_infer())
8496
}
8597
}
@@ -90,7 +102,7 @@ impl<
90102
I: Interner,
91103
const VISIT_PLACEHOLDER: bool,
92104
const VISIT_INFER: bool,
93-
> TypeVisitor<I> for MaxUniverse<'a, Infcx, VISIT_PLACEHOLDER, VISIT_INFER>
105+
> TypeVisitor<I> for MaxUniverse<'a, Infcx, I, VISIT_PLACEHOLDER, VISIT_INFER>
94106
{
95107
type Result = ();
96108

@@ -99,6 +111,10 @@ impl<
99111
return;
100112
}
101113

114+
if self.cache.contains(&t) {
115+
return;
116+
}
117+
102118
match t.kind() {
103119
TyKind::Placeholder(p) if VISIT_PLACEHOLDER => {
104120
self.max_universe = self.max_universe.max(p.universe)
@@ -110,6 +126,8 @@ impl<
110126
}
111127
_ => t.super_visit_with(self),
112128
}
129+
130+
assert!(self.cache.insert(t), "we shouldn't visit {t:?} twice");
113131
}
114132

115133
fn visit_const(&mut self, c: I::Const) {

0 commit comments

Comments
 (0)