Skip to content

Commit cdb96be

Browse files
committed
Handle placeholder types in canonicalization
1 parent 91623ca commit cdb96be

File tree

5 files changed

+85
-21
lines changed

5 files changed

+85
-21
lines changed

src/librustc/ich/impls_ty.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,12 +1099,13 @@ impl_stable_hash_for!(struct infer::canonical::CanonicalVarInfo {
10991099

11001100
impl_stable_hash_for!(enum infer::canonical::CanonicalVarKind {
11011101
Ty(k),
1102+
PlaceholderTy(placeholder),
11021103
Region(ui),
11031104
PlaceholderRegion(placeholder),
11041105
});
11051106

11061107
impl_stable_hash_for!(enum infer::canonical::CanonicalTyVarKind {
1107-
General,
1108+
General(ui),
11081109
Int,
11091110
Float
11101111
});

src/librustc/infer/canonical/canonicalizer.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -339,18 +339,49 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
339339

340340
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
341341
match t.sty {
342-
ty::Infer(ty::TyVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::General, t),
342+
ty::Infer(ty::TyVar(vid)) => {
343+
match self.infcx.unwrap().probe_ty_var(vid) {
344+
// `t` could be a float / int variable: canonicalize that instead
345+
Ok(t) => self.fold_ty(t),
346+
347+
// `TyVar(vid)` is unresolved, track its universe index in the canonicalized
348+
// result
349+
Err(ui) => self.canonicalize_ty_var(
350+
CanonicalVarInfo {
351+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
352+
},
353+
t
354+
)
355+
}
356+
}
343357

344-
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Int, t),
358+
ty::Infer(ty::IntVar(_)) => self.canonicalize_ty_var(
359+
CanonicalVarInfo {
360+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
361+
},
362+
t
363+
),
345364

346-
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(CanonicalTyVarKind::Float, t),
365+
ty::Infer(ty::FloatVar(_)) => self.canonicalize_ty_var(
366+
CanonicalVarInfo {
367+
kind: CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
368+
},
369+
t
370+
),
347371

348372
ty::Infer(ty::FreshTy(_))
349373
| ty::Infer(ty::FreshIntTy(_))
350374
| ty::Infer(ty::FreshFloatTy(_)) => {
351375
bug!("encountered a fresh type during canonicalization")
352376
}
353377

378+
ty::Placeholder(placeholder) => self.canonicalize_ty_var(
379+
CanonicalVarInfo {
380+
kind: CanonicalVarKind::PlaceholderTy(placeholder)
381+
},
382+
t
383+
),
384+
354385
ty::Bound(bound_ty) => {
355386
if bound_ty.index >= self.binder_index {
356387
bug!("escaping bound type during canonicalization")
@@ -380,7 +411,6 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Canonicalizer<'cx, 'gcx, 'tcx>
380411
| ty::Never
381412
| ty::Tuple(..)
382413
| ty::Projection(..)
383-
| ty::Placeholder(..)
384414
| ty::UnnormalizedProjection(..)
385415
| ty::Foreign(..)
386416
| ty::Param(..)
@@ -579,15 +609,12 @@ impl<'cx, 'gcx, 'tcx> Canonicalizer<'cx, 'gcx, 'tcx> {
579609
/// if `ty_var` is bound to anything; if so, canonicalize
580610
/// *that*. Otherwise, create a new canonical variable for
581611
/// `ty_var`.
582-
fn canonicalize_ty_var(&mut self, ty_kind: CanonicalTyVarKind, ty_var: Ty<'tcx>) -> Ty<'tcx> {
612+
fn canonicalize_ty_var(&mut self, info: CanonicalVarInfo, ty_var: Ty<'tcx>) -> Ty<'tcx> {
583613
let infcx = self.infcx.expect("encountered ty-var without infcx");
584614
let bound_to = infcx.shallow_resolve(ty_var);
585615
if bound_to != ty_var {
586616
self.fold_ty(bound_to)
587617
} else {
588-
let info = CanonicalVarInfo {
589-
kind: CanonicalVarKind::Ty(ty_kind),
590-
};
591618
let var = self.canonical_var(info, ty_var.into());
592619
self.tcx().mk_ty(ty::Bound(BoundTy::new(self.binder_index, var)))
593620
}

src/librustc/infer/canonical/mod.rs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ impl CanonicalVarInfo {
122122
pub fn is_existential(&self) -> bool {
123123
match self.kind {
124124
CanonicalVarKind::Ty(_) => true,
125+
CanonicalVarKind::PlaceholderTy(_) => false,
125126
CanonicalVarKind::Region(_) => true,
126127
CanonicalVarKind::PlaceholderRegion(..) => false,
127128
}
@@ -136,6 +137,9 @@ pub enum CanonicalVarKind {
136137
/// Some kind of type inference variable.
137138
Ty(CanonicalTyVarKind),
138139

140+
/// A "placeholder" that represents "any type".
141+
PlaceholderTy(ty::PlaceholderType),
142+
139143
/// Region variable `'?R`.
140144
Region(ty::UniverseIndex),
141145

@@ -148,12 +152,12 @@ pub enum CanonicalVarKind {
148152
impl CanonicalVarKind {
149153
pub fn universe(self) -> ty::UniverseIndex {
150154
match self {
151-
// At present, we don't support higher-ranked
152-
// quantification over types, so all type variables are in
153-
// the root universe.
154-
CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
155+
CanonicalVarKind::Ty(kind) => match kind {
156+
CanonicalTyVarKind::General(ui) => ui,
157+
CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
158+
}
155159

156-
// Region variables can be created in sub-universes.
160+
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
157161
CanonicalVarKind::Region(ui) => ui,
158162
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
159163
}
@@ -168,7 +172,7 @@ impl CanonicalVarKind {
168172
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
169173
pub enum CanonicalTyVarKind {
170174
/// General type variable `?T` that can be unified with arbitrary types.
171-
General,
175+
General(ty::UniverseIndex),
172176

173177
/// Integral type variable `?I` (that can only be unified with integral types).
174178
Int,
@@ -358,8 +362,11 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
358362
match cv_info.kind {
359363
CanonicalVarKind::Ty(ty_kind) => {
360364
let ty = match ty_kind {
361-
CanonicalTyVarKind::General => {
362-
self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
365+
CanonicalTyVarKind::General(ui) => {
366+
self.next_ty_var_in_universe(
367+
TypeVariableOrigin::MiscVariable(span),
368+
universe_map(ui)
369+
)
363370
}
364371

365372
CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
@@ -369,6 +376,15 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
369376
ty.into()
370377
}
371378

379+
CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
380+
let universe_mapped = universe_map(universe);
381+
let placeholder_mapped = ty::PlaceholderType {
382+
universe: universe_mapped,
383+
name,
384+
};
385+
self.tcx.mk_ty(ty::Placeholder(placeholder_mapped)).into()
386+
}
387+
372388
CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
373389
RegionVariableOrigin::MiscVariable(span),
374390
universe_map(ui),
@@ -380,9 +396,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
380396
universe: universe_mapped,
381397
name,
382398
};
383-
self.tcx
384-
.mk_region(ty::RePlaceholder(placeholder_mapped))
385-
.into()
399+
self.tcx.mk_region(ty::RePlaceholder(placeholder_mapped)).into()
386400
}
387401
}
388402
}

src/librustc/infer/mod.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -972,6 +972,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
972972
self.tcx.mk_var(self.next_ty_var_id(false, origin))
973973
}
974974

975+
pub fn next_ty_var_in_universe(
976+
&self,
977+
origin: TypeVariableOrigin,
978+
universe: ty::UniverseIndex
979+
) -> Ty<'tcx> {
980+
let vid = self.type_variables
981+
.borrow_mut()
982+
.new_var(universe, false, origin);
983+
self.tcx.mk_var(vid)
984+
}
985+
975986
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
976987
self.tcx.mk_var(self.next_ty_var_id(true, origin))
977988
}
@@ -1227,6 +1238,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
12271238
}
12281239
}
12291240

1241+
/// If `TyVar(vid)` resolves to a type, return that type. Else, return the
1242+
/// universe index of `TyVar(vid)`.
1243+
pub fn probe_ty_var(&self, vid: TyVid) -> Result<Ty<'tcx>, ty::UniverseIndex> {
1244+
use self::type_variable::TypeVariableValue;
1245+
1246+
match self.type_variables.borrow_mut().probe(vid) {
1247+
TypeVariableValue::Known { value } => Ok(value),
1248+
TypeVariableValue::Unknown { universe } => Err(universe),
1249+
}
1250+
}
1251+
12301252
pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
12311253
self.inlined_shallow_resolve(typ)
12321254
}

src/librustc/infer/type_variable.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
7272

7373
struct TypeVariableData {
7474
origin: TypeVariableOrigin,
75-
diverging: bool
75+
diverging: bool,
7676
}
7777

7878
#[derive(Copy, Clone, Debug)]

0 commit comments

Comments
 (0)