Skip to content

Commit de2dcd6

Browse files
committed
add universes to type inference variables
1 parent 64918a2 commit de2dcd6

File tree

20 files changed

+132
-55
lines changed

20 files changed

+132
-55
lines changed

src/librustc/infer/combine.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
393393
drop(variables);
394394
self.relate(&u, &u)
395395
}
396-
TypeVariableValue::Unknown { .. } => {
396+
TypeVariableValue::Unknown { universe } => {
397397
match self.ambient_variance {
398398
// Invariant: no need to make a fresh type variable.
399399
ty::Invariant => return Ok(t),
@@ -410,7 +410,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
410410
}
411411

412412
let origin = *variables.var_origin(vid);
413-
let new_var_id = variables.new_var(false, origin);
413+
let new_var_id = variables.new_var(universe, false, origin);
414414
let u = self.tcx().mk_var(new_var_id);
415415
debug!("generalize: replacing original vid={:?} with new={:?}",
416416
vid, u);

src/librustc/infer/fudge.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
141141
// This variable was created during the
142142
// fudging. Recreate it with a fresh variable
143143
// here.
144-
self.infcx.next_ty_var(origin)
144+
//
145+
// The ROOT universe is fine because we only
146+
// ever invoke this routine at the
147+
// "item-level" of inference.
148+
self.infcx.next_ty_var(ty::UniverseIndex::ROOT, origin)
145149
}
146150
}
147151
}

src/librustc/infer/lattice.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,17 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
8888
// is (e.g.) `Box<i32>`. A more obvious solution might be to
8989
// iterate on the subtype obligations that are returned, but I
9090
// think this suffices. -nmatsakis
91-
(&ty::TyInfer(TyVar(..)), _) => {
92-
let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
91+
(&ty::TyInfer(TyVar(a_vid)), _) => {
92+
let universe = infcx.type_variables.borrow_mut().probe(a_vid).universe().unwrap();
93+
let v = infcx.next_ty_var(universe,
94+
TypeVariableOrigin::LatticeVariable(this.cause().span));
9395
this.relate_bound(v, b, a)?;
9496
Ok(v)
9597
}
96-
(_, &ty::TyInfer(TyVar(..))) => {
97-
let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
98+
(_, &ty::TyInfer(TyVar(b_vid))) => {
99+
let universe = infcx.type_variables.borrow_mut().probe(b_vid).universe().unwrap();
100+
let v = infcx.next_ty_var(universe,
101+
TypeVariableOrigin::LatticeVariable(this.cause().span));
98102
this.relate_bound(v, a, b)?;
99103
Ok(v)
100104
}

src/librustc/infer/mod.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -942,18 +942,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
942942
})
943943
}
944944

945-
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
945+
pub fn next_ty_var_id(&self,
946+
universe: ty::UniverseIndex,
947+
diverging: bool,
948+
origin: TypeVariableOrigin)
949+
-> TyVid {
946950
self.type_variables
947951
.borrow_mut()
948-
.new_var(diverging, origin)
952+
.new_var(universe, diverging, origin)
949953
}
950954

951-
pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
952-
self.tcx.mk_var(self.next_ty_var_id(false, origin))
955+
pub fn next_ty_var(&self, universe: ty::UniverseIndex, origin: TypeVariableOrigin) -> Ty<'tcx> {
956+
self.tcx.mk_var(self.next_ty_var_id(universe, false, origin))
953957
}
954958

955-
pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
956-
self.tcx.mk_var(self.next_ty_var_id(true, origin))
959+
pub fn next_diverging_ty_var(&self, universe: ty::UniverseIndex, origin: TypeVariableOrigin) -> Ty<'tcx> {
960+
self.tcx.mk_var(self.next_ty_var_id(universe, true, origin))
957961
}
958962

959963
pub fn next_int_var_id(&self) -> IntVid {
@@ -991,12 +995,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
991995
/// use an inference variable for `C` with `[T, U]`
992996
/// as the substitutions for the default, `(T, U)`.
993997
pub fn type_var_for_def(&self,
998+
universe: ty::UniverseIndex,
994999
span: Span,
9951000
def: &ty::TypeParameterDef)
9961001
-> Ty<'tcx> {
9971002
let ty_var_id = self.type_variables
9981003
.borrow_mut()
999-
.new_var(false,
1004+
.new_var(universe,
1005+
false,
10001006
TypeVariableOrigin::TypeParameterDefinition(span, def.name));
10011007

10021008
self.tcx.mk_var(ty_var_id)
@@ -1005,13 +1011,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10051011
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
10061012
/// type/region parameter to a fresh inference variable.
10071013
pub fn fresh_substs_for_item(&self,
1014+
universe: ty::UniverseIndex,
10081015
span: Span,
10091016
def_id: DefId)
10101017
-> &'tcx Substs<'tcx> {
10111018
Substs::for_item(self.tcx, def_id, |def, _| {
10121019
self.region_var_for_def(span, def)
10131020
}, |def, _| {
1014-
self.type_var_for_def(span, def)
1021+
self.type_var_for_def(universe, span, def)
10151022
})
10161023
}
10171024

src/librustc/infer/type_variable.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use syntax::ast;
1212
use syntax_pos::Span;
1313
use ty::{self, Ty};
1414

15+
use std::cmp;
1516
use std::marker::PhantomData;
1617
use std::u32;
1718
use rustc_data_structures::fx::FxHashMap;
@@ -78,17 +79,33 @@ struct TypeVariableData {
7879
#[derive(Copy, Clone, Debug)]
7980
pub enum TypeVariableValue<'tcx> {
8081
Known { value: Ty<'tcx> },
81-
Unknown,
82+
Unknown { universe: ty::UniverseIndex },
83+
}
84+
85+
#[derive(Copy, Clone, Debug)]
86+
pub enum ProbeTyValue<'tcx> {
87+
Ty(Ty<'tcx>),
88+
Vid(ty::TyVid),
8289
}
8390

8491
impl<'tcx> TypeVariableValue<'tcx> {
92+
/// If this value is known, returns the type it is known to be.
93+
/// Otherwise, `None`.
8594
pub fn known(&self) -> Option<Ty<'tcx>> {
8695
match *self {
8796
TypeVariableValue::Unknown { .. } => None,
8897
TypeVariableValue::Known { value } => Some(value),
8998
}
9099
}
91100

101+
/// If this value is unknown, returns the universe, otherwise `None`.
102+
pub fn universe(&self) -> Option<ty::UniverseIndex> {
103+
match *self {
104+
TypeVariableValue::Unknown { universe } => Some(universe),
105+
TypeVariableValue::Known { .. } => None,
106+
}
107+
}
108+
92109
pub fn is_unknown(&self) -> bool {
93110
match *self {
94111
TypeVariableValue::Unknown { .. } => true,
@@ -175,10 +192,11 @@ impl<'tcx> TypeVariableTable<'tcx> {
175192
/// The code in this module doesn't care, but it can be useful
176193
/// for improving error messages.
177194
pub fn new_var(&mut self,
195+
universe: ty::UniverseIndex,
178196
diverging: bool,
179197
origin: TypeVariableOrigin)
180198
-> ty::TyVid {
181-
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown);
199+
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe });
182200

183201
let sub_key = self.sub_relations.new_key(());
184202
assert_eq!(eq_key.vid, sub_key);
@@ -385,8 +403,12 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
385403
(&TypeVariableValue::Known { .. }, &TypeVariableValue::Unknown { .. }) => Ok(*value1),
386404
(&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),
387405

388-
// If both sides are *unknown*, it hardly matters, does it?
389-
(&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1),
406+
// If both sides are unknown, we need to pick the most restrictive universe.
407+
(&TypeVariableValue::Unknown { universe: universe1 },
408+
&TypeVariableValue::Unknown { universe: universe2 }) => {
409+
let universe = cmp::min(universe1, universe2);
410+
Ok(TypeVariableValue::Unknown { universe })
411+
}
390412
}
391413
}
392414
}

src/librustc/traits/coherence.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, '
5050
-> ty::ImplHeader<'tcx>
5151
{
5252
let tcx = selcx.tcx();
53-
let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
53+
let impl_substs = selcx.infcx().fresh_substs_for_item(param_env.universe,
54+
DUMMY_SP,
55+
impl_def_id);
5456

5557
let header = ty::ImplHeader {
5658
impl_def_id,

src/librustc/traits/error_reporting.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
285285

286286
self.tcx.for_each_relevant_impl(
287287
trait_ref.def_id, trait_self_ty, |def_id| {
288-
let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
288+
let impl_substs = self.fresh_substs_for_item(param_env.universe,
289+
obligation.cause.span,
290+
def_id);
289291
let impl_trait_ref = tcx
290292
.impl_trait_ref(def_id)
291293
.unwrap()
@@ -1134,6 +1136,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11341136
-> bool {
11351137
struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
11361138
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
1139+
param_env: ty::ParamEnv<'tcx>,
11371140
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>
11381141
}
11391142

@@ -1143,9 +1146,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11431146
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
11441147
if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty {
11451148
let infcx = self.infcx;
1146-
self.var_map.entry(ty).or_insert_with(||
1147-
infcx.next_ty_var(
1148-
TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name)))
1149+
let param_env = self.param_env;
1150+
self.var_map
1151+
.entry(ty)
1152+
.or_insert_with(|| {
1153+
let origin = TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP,
1154+
name);
1155+
infcx.next_ty_var(param_env.universe, origin)
1156+
})
11491157
} else {
11501158
ty.super_fold_with(self)
11511159
}
@@ -1157,6 +1165,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
11571165

11581166
let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
11591167
infcx: self,
1168+
param_env,
11601169
var_map: FxHashMap()
11611170
});
11621171

src/librustc/traits/project.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
404404
let tcx = selcx.infcx().tcx;
405405
let def_id = projection_ty.item_def_id;
406406
let ty_var = selcx.infcx().next_ty_var(
407+
param_env.universe,
407408
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
408409
let projection = ty::Binder(ty::ProjectionPredicate {
409410
projection_ty,
@@ -724,6 +725,7 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
724725
let tcx = selcx.infcx().tcx;
725726
let def_id = projection_ty.item_def_id;
726727
let new_value = selcx.infcx().next_ty_var(
728+
param_env.universe,
727729
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
728730
Normalized {
729731
value: new_value,

src/librustc/traits/select.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3031,7 +3031,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
30313031
snapshot);
30323032
let skol_obligation_trait_ref = skol_obligation.trait_ref;
30333033

3034-
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
3034+
let impl_substs = self.infcx.fresh_substs_for_item(obligation.param_env.universe,
3035+
obligation.cause.span,
30353036
impl_def_id);
30363037

30373038
let impl_trait_ref = impl_trait_ref.subst(self.tcx(),

src/librustc/traits/specialize/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
217217
target_impl: DefId)
218218
-> Result<&'tcx Substs<'tcx>, ()> {
219219
let selcx = &mut SelectionContext::new(&infcx);
220-
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
220+
let target_substs = infcx.fresh_substs_for_item(param_env.universe, DUMMY_SP, target_impl);
221221
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
222222
param_env,
223223
target_impl,

src/librustc_typeck/check/_match.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
285285
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
286286
// FIXME: MiscVariable for now, obtaining the span and name information
287287
// from all tuple elements isn't trivial.
288+
ty::UniverseIndex::ROOT,
288289
TypeVariableOrigin::TypeInference(pat.span)));
289290
let element_tys = tcx.mk_type_list(element_tys_iter);
290291
let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
@@ -295,7 +296,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
295296
pat_ty
296297
}
297298
PatKind::Box(ref inner) => {
298-
let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
299+
let inner_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
300+
TypeVariableOrigin::TypeInference(inner.span));
299301
let uniq_ty = tcx.mk_box(inner_ty);
300302

301303
if self.check_dereferencable(pat.span, expected, &inner) {
@@ -328,6 +330,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
328330
}
329331
_ => {
330332
let inner_ty = self.next_ty_var(
333+
ty::UniverseIndex::ROOT,
331334
TypeVariableOrigin::TypeInference(inner.span));
332335
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
333336
let region = self.next_region_var(infer::PatternRegion(pat.span));
@@ -571,7 +574,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
571574
// ...but otherwise we want to use any supertype of the
572575
// discriminant. This is sort of a workaround, see note (*) in
573576
// `check_pat` for some details.
574-
discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
577+
discrim_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
578+
TypeVariableOrigin::TypeInference(discrim.span));
575579
self.check_expr_has_type_or_error(discrim, discrim_ty);
576580
};
577581

@@ -632,7 +636,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
632636
// arm for inconsistent arms or to the whole match when a `()` type
633637
// is required).
634638
Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
635-
_ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
639+
_ => self.next_ty_var(ty::UniverseIndex::ROOT,
640+
TypeVariableOrigin::MiscVariable(expr.span)),
636641
};
637642
CoerceMany::with_coercion_sites(coerce_first, arms)
638643
};

src/librustc_typeck/check/closure.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
100100
|_, _| span_bug!(expr.span, "closure has region param"),
101101
|_, _| {
102102
self.infcx
103-
.next_ty_var(TypeVariableOrigin::TransformedUpvar(expr.span))
103+
.next_ty_var(ty::UniverseIndex::ROOT,
104+
TypeVariableOrigin::TransformedUpvar(expr.span))
104105
},
105106
);
106107
let closure_type = self.tcx.mk_closure(expr_def_id, substs);

src/librustc_typeck/check/coercion.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
179179
// micro-optimization: no need for this if `b` is
180180
// already resolved in some way.
181181
let diverging_ty = self.next_diverging_ty_var(
182+
ty::UniverseIndex::ROOT,
182183
TypeVariableOrigin::AdjustmentType(self.cause.span));
183184
self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
184185
} else {
@@ -497,7 +498,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
497498
// We only have the latter, so we use an inference variable
498499
// for the former and let type inference do the rest.
499500
let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
500-
let coerce_target = self.next_ty_var(origin);
501+
let coerce_target = self.next_ty_var(ty::UniverseIndex::ROOT, origin);
501502
let mut coercion = self.unify_and(coerce_target, target, |target| {
502503
let unsize = Adjustment {
503504
kind: Adjust::Unsize,

src/librustc_typeck/check/dropck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
8888

8989
let drop_impl_span = tcx.def_span(drop_impl_did);
9090
let fresh_impl_substs =
91-
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
91+
infcx.fresh_substs_for_item(ty::UniverseIndex::ROOT, drop_impl_span, drop_impl_did);
9292
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
9393

9494
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id);

src/librustc_typeck/check/method/confirm.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
240240
// the process we will unify the transformed-self-type
241241
// of the method with the actual type in order to
242242
// unify some of these variables.
243-
self.fresh_substs_for_item(self.span, trait_def_id)
243+
self.fresh_substs_for_item(ty::UniverseIndex::ROOT, self.span, trait_def_id)
244244
}
245245

246246
probe::WhereClausePick(ref poly_trait_ref) => {
@@ -316,7 +316,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
316316
{
317317
self.to_ty(ast_ty)
318318
} else {
319-
self.type_var_for_def(self.span, def)
319+
self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def)
320320
}
321321
})
322322
}

src/librustc_typeck/check/method/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
255255
} else if let Some(ref input_types) = opt_input_types {
256256
input_types[def.index as usize - 1]
257257
} else {
258-
self.type_var_for_def(span, def)
258+
self.type_var_for_def(ty::UniverseIndex::ROOT, span, def)
259259
}
260260
});
261261

0 commit comments

Comments
 (0)