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
5 changes: 3 additions & 2 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -853,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 @@ -921,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