Skip to content
4 changes: 2 additions & 2 deletions src/librustc/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
drop(variables);
self.relate(&u, &u)
}
TypeVariableValue::Unknown { .. } => {
TypeVariableValue::Unknown { universe } => {
match self.ambient_variance {
// Invariant: no need to make a fresh type variable.
ty::Invariant => return Ok(t),
Expand All @@ -424,7 +424,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, '
}

let origin = *variables.var_origin(vid);
let new_var_id = variables.new_var(false, origin);
let new_var_id = variables.new_var(universe, false, origin);
let u = self.tcx().mk_var(new_var_id);
debug!("generalize: replacing original vid={:?} with new={:?}",
vid, u);
Expand Down
17 changes: 15 additions & 2 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
// obligations within. This is expected to be done 'late enough'
// that all type inference variables have been bound and so forth.
pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,

/// What is the innermost universe we have created? Starts out as
/// `UniverseIndex::root()` but grows from there as we enter
/// universal quantifiers.
///
/// NB: At present, we exclude the universal quantifiers on the
/// item we are type-checking, and just consider those names as
/// part of the root universe. So this would only get incremented
/// when we enter into a higher-ranked (`for<..>`) type or trait
/// bound.
pub universe: ty::UniverseIndex,
}

/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
Expand Down Expand Up @@ -455,6 +466,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
err_count_on_creation: tcx.sess.err_count(),
in_snapshot: Cell::new(false),
region_obligations: RefCell::new(vec![]),
universe: ty::UniverseIndex::ROOT,
}))
}
}
Expand Down Expand Up @@ -841,7 +853,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
self.type_variables
.borrow_mut()
.new_var(diverging, origin)
.new_var(self.universe, diverging, origin)
}

pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
Expand Down Expand Up @@ -909,7 +921,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-> Ty<'tcx> {
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(false,
.new_var(self.universe,
false,
TypeVariableOrigin::TypeParameterDefinition(span, def.name));

self.tcx.mk_var(ty_var_id)
Expand Down
13 changes: 10 additions & 3 deletions src/librustc/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ struct TypeVariableData {
#[derive(Copy, Clone, Debug)]
pub enum TypeVariableValue<'tcx> {
Known { value: Ty<'tcx> },
Unknown,
Unknown { universe: ty::UniverseIndex },
}

impl<'tcx> TypeVariableValue<'tcx> {
/// If this value is known, returns the type it is known to be.
/// Otherwise, `None`.
pub fn known(&self) -> Option<Ty<'tcx>> {
match *self {
TypeVariableValue::Unknown { .. } => None,
Expand Down Expand Up @@ -181,10 +183,11 @@ impl<'tcx> TypeVariableTable<'tcx> {
/// The code in this module doesn't care, but it can be useful
/// for improving error messages.
pub fn new_var(&mut self,
universe: ty::UniverseIndex,
diverging: bool,
origin: TypeVariableOrigin)
-> ty::TyVid {
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown);
let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe });

let sub_key = self.sub_relations.new_key(());
assert_eq!(eq_key.vid, sub_key);
Expand Down Expand Up @@ -437,7 +440,11 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
(&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),

// If both sides are *unknown*, it hardly matters, does it?
(&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1),
(&TypeVariableValue::Unknown { universe: universe1 },
&TypeVariableValue::Unknown { universe: universe2 }) => {
let universe = cmp::min(universe1, universe2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth adding a comment here. Something like this:


If we have two unbound variables, ?T and ?U, that get unified, then whatever value they wind up taking (which must be the same value) must be nameable by both. Therefore, the resulting universe is the minimum of the two universes, because that is the one which contains the fewest names in scope.

Ok(TypeVariableValue::Unknown { universe })
}
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,9 +1376,7 @@ pub struct UniverseIndex(u32);
impl UniverseIndex {
/// The root universe, where things that the user defined are
/// visible.
pub fn root() -> UniverseIndex {
UniverseIndex(0)
}
pub const ROOT: Self = UniverseIndex(0);

/// A "subuniverse" corresponds to being inside a `forall` quantifier.
/// So, for example, suppose we have this type in universe `U`:
Expand Down