Skip to content

Commit

Permalink
add universes to type inference variables
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis authored and sgrif committed Mar 1, 2018
1 parent 44d9929 commit 13efaf0
Show file tree
Hide file tree
Showing 21 changed files with 132 additions and 55 deletions.
3 changes: 2 additions & 1 deletion src/librustc/infer/anon_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,8 @@ impl<'a, 'gcx, 'tcx> Instantiator<'a, 'gcx, 'tcx> {
return anon_defn.concrete_ty;
}
let span = tcx.def_span(def_id);
let ty_var = infcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
let ty_var = infcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(span));

let predicates_of = tcx.predicates_of(def_id);
let bounds = predicates_of.instantiate(tcx, substs);
Expand Down
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
6 changes: 5 additions & 1 deletion src/librustc/infer/fudge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
// This variable was created during the
// fudging. Recreate it with a fresh variable
// here.
self.infcx.next_ty_var(origin)
//
// The ROOT universe is fine because we only
// ever invoke this routine at the
// "item-level" of inference.
self.infcx.next_ty_var(ty::UniverseIndex::ROOT, origin)
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/librustc/infer/lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,17 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
// is (e.g.) `Box<i32>`. A more obvious solution might be to
// iterate on the subtype obligations that are returned, but I
// think this suffices. -nmatsakis
(&ty::TyInfer(TyVar(..)), _) => {
let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
(&ty::TyInfer(TyVar(a_vid)), _) => {
let universe = infcx.type_variables.borrow_mut().probe(a_vid).universe().unwrap();
let v = infcx.next_ty_var(universe,
TypeVariableOrigin::LatticeVariable(this.cause().span));
this.relate_bound(v, b, a)?;
Ok(v)
}
(_, &ty::TyInfer(TyVar(..))) => {
let v = infcx.next_ty_var(TypeVariableOrigin::LatticeVariable(this.cause().span));
(_, &ty::TyInfer(TyVar(b_vid))) => {
let universe = infcx.type_variables.borrow_mut().probe(b_vid).universe().unwrap();
let v = infcx.next_ty_var(universe,
TypeVariableOrigin::LatticeVariable(this.cause().span));
this.relate_bound(v, a, b)?;
Ok(v)
}
Expand Down
23 changes: 15 additions & 8 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1015,18 +1015,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
})
}

pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {
pub fn next_ty_var_id(&self,
universe: ty::UniverseIndex,
diverging: bool,
origin: TypeVariableOrigin)
-> TyVid {
self.type_variables
.borrow_mut()
.new_var(diverging, origin)
.new_var(universe, diverging, origin)
}

pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(false, origin))
pub fn next_ty_var(&self, universe: ty::UniverseIndex, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(universe, false, origin))
}

pub fn next_diverging_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(true, origin))
pub fn next_diverging_ty_var(&self, universe: ty::UniverseIndex, origin: TypeVariableOrigin) -> Ty<'tcx> {
self.tcx.mk_var(self.next_ty_var_id(universe, true, origin))
}

pub fn next_int_var_id(&self) -> IntVid {
Expand Down Expand Up @@ -1081,12 +1085,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// use an inference variable for `C` with `[T, U]`
/// as the substitutions for the default, `(T, U)`.
pub fn type_var_for_def(&self,
universe: ty::UniverseIndex,
span: Span,
def: &ty::TypeParameterDef)
-> Ty<'tcx> {
let ty_var_id = self.type_variables
.borrow_mut()
.new_var(false,
.new_var(universe,
false,
TypeVariableOrigin::TypeParameterDefinition(span, def.name));

self.tcx.mk_var(ty_var_id)
Expand All @@ -1095,13 +1101,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
/// type/region parameter to a fresh inference variable.
pub fn fresh_substs_for_item(&self,
universe: ty::UniverseIndex,
span: Span,
def_id: DefId)
-> &'tcx Substs<'tcx> {
Substs::for_item(self.tcx, def_id, |def, _| {
self.region_var_for_def(span, def)
}, |def, _| {
self.type_var_for_def(span, def)
self.type_var_for_def(universe, span, def)
})
}

Expand Down
30 changes: 26 additions & 4 deletions src/librustc/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use syntax::ast;
use syntax_pos::Span;
use ty::{self, Ty};

use std::cmp;
use std::marker::PhantomData;
use std::u32;
use rustc_data_structures::fx::FxHashMap;
Expand Down Expand Up @@ -81,17 +82,33 @@ struct TypeVariableData {
#[derive(Copy, Clone, Debug)]
pub enum TypeVariableValue<'tcx> {
Known { value: Ty<'tcx> },
Unknown,
Unknown { universe: ty::UniverseIndex },
}

#[derive(Copy, Clone, Debug)]
pub enum ProbeTyValue<'tcx> {
Ty(Ty<'tcx>),
Vid(ty::TyVid),
}

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,
TypeVariableValue::Known { value } => Some(value),
}
}

/// If this value is unknown, returns the universe, otherwise `None`.
pub fn universe(&self) -> Option<ty::UniverseIndex> {
match *self {
TypeVariableValue::Unknown { universe } => Some(universe),
TypeVariableValue::Known { .. } => None,
}
}

pub fn is_unknown(&self) -> bool {
match *self {
TypeVariableValue::Unknown { .. } => true,
Expand Down Expand Up @@ -178,10 +195,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 @@ -388,8 +406,12 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> {
(&TypeVariableValue::Known { .. }, &TypeVariableValue::Unknown { .. }) => Ok(*value1),
(&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2),

// If both sides are *unknown*, it hardly matters, does it?
(&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1),
// If both sides are unknown, we need to pick the most restrictive universe.
(&TypeVariableValue::Unknown { universe: universe1 },
&TypeVariableValue::Unknown { universe: universe2 }) => {
let universe = cmp::min(universe1, universe2);
Ok(TypeVariableValue::Unknown { universe })
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, '
-> ty::ImplHeader<'tcx>
{
let tcx = selcx.tcx();
let impl_substs = selcx.infcx().fresh_substs_for_item(DUMMY_SP, impl_def_id);
let impl_substs = selcx.infcx().fresh_substs_for_item(param_env.universe,
DUMMY_SP,
impl_def_id);

let header = ty::ImplHeader {
impl_def_id,
Expand Down
17 changes: 13 additions & 4 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

self.tcx.for_each_relevant_impl(
trait_ref.def_id, trait_self_ty, |def_id| {
let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id);
let impl_substs = self.fresh_substs_for_item(param_env.universe,
obligation.cause.span,
def_id);
let impl_trait_ref = tcx
.impl_trait_ref(def_id)
.unwrap()
Expand Down Expand Up @@ -1194,6 +1196,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-> bool {
struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>
}

Expand All @@ -1203,9 +1206,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty {
let infcx = self.infcx;
self.var_map.entry(ty).or_insert_with(||
infcx.next_ty_var(
TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name)))
let param_env = self.param_env;
self.var_map
.entry(ty)
.or_insert_with(|| {
let origin = TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP,
name);
infcx.next_ty_var(param_env.universe, origin)
})
} else {
ty.super_fold_with(self)
}
Expand All @@ -1217,6 +1225,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {

let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
infcx: self,
param_env,
var_map: FxHashMap()
});

Expand Down
2 changes: 2 additions & 0 deletions src/librustc/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ pub fn normalize_projection_type<'a, 'b, 'gcx, 'tcx>(
let tcx = selcx.infcx().tcx;
let def_id = projection_ty.item_def_id;
let ty_var = selcx.infcx().next_ty_var(
param_env.universe,
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
let projection = ty::Binder(ty::ProjectionPredicate {
projection_ty,
Expand Down Expand Up @@ -789,6 +790,7 @@ fn normalize_to_error<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tc
let tcx = selcx.infcx().tcx;
let def_id = projection_ty.item_def_id;
let new_value = selcx.infcx().next_ty_var(
param_env.universe,
TypeVariableOrigin::NormalizeProjectionType(tcx.def_span(def_id)));
Normalized {
value: new_value,
Expand Down
3 changes: 2 additions & 1 deletion src/librustc/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3111,7 +3111,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
snapshot);
let skol_obligation_trait_ref = skol_obligation.trait_ref;

let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
let impl_substs = self.infcx.fresh_substs_for_item(obligation.param_env.universe,
obligation.cause.span,
impl_def_id);

let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
target_impl: DefId)
-> Result<&'tcx Substs<'tcx>, ()> {
let selcx = &mut SelectionContext::new(&infcx);
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
let target_substs = infcx.fresh_substs_for_item(param_env.universe, DUMMY_SP, target_impl);
let (target_trait_ref, mut obligations) = impl_trait_ref_and_oblig(selcx,
param_env,
target_impl,
Expand Down
11 changes: 8 additions & 3 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(
// FIXME: MiscVariable for now, obtaining the span and name information
// from all tuple elements isn't trivial.
ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(pat.span)));
let element_tys = tcx.mk_type_list(element_tys_iter);
let pat_ty = tcx.mk_ty(ty::TyTuple(element_tys, false));
Expand All @@ -339,7 +340,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
pat_ty
}
PatKind::Box(ref inner) => {
let inner_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(inner.span));
let inner_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(inner.span));
let uniq_ty = tcx.mk_box(inner_ty);

if self.check_dereferencable(pat.span, expected, &inner) {
Expand Down Expand Up @@ -372,6 +374,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
}
_ => {
let inner_ty = self.next_ty_var(
ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(inner.span));
let mt = ty::TypeAndMut { ty: inner_ty, mutbl: mutbl };
let region = self.next_region_var(infer::PatternRegion(pat.span));
Expand Down Expand Up @@ -630,7 +633,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
// ...but otherwise we want to use any supertype of the
// discriminant. This is sort of a workaround, see note (*) in
// `check_pat` for some details.
discrim_ty = self.next_ty_var(TypeVariableOrigin::TypeInference(discrim.span));
discrim_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(discrim.span));
self.check_expr_has_type_or_error(discrim, discrim_ty);
};

Expand Down Expand Up @@ -691,7 +695,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
// arm for inconsistent arms or to the whole match when a `()` type
// is required).
Expectation::ExpectHasType(ety) if ety != self.tcx.mk_nil() => ety,
_ => self.next_ty_var(TypeVariableOrigin::MiscVariable(expr.span)),
_ => self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(expr.span)),
};
CoerceMany::with_coercion_sites(coerce_first, arms)
};
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/closure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|_, _| span_bug!(expr.span, "closure has region param"),
|_, _| {
self.infcx
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))
.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::ClosureSynthetic(expr.span))
},
);
let substs = ty::ClosureSubsts { substs };
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
// micro-optimization: no need for this if `b` is
// already resolved in some way.
let diverging_ty = self.next_diverging_ty_var(
ty::UniverseIndex::ROOT,
TypeVariableOrigin::AdjustmentType(self.cause.span));
self.unify_and(&b, &diverging_ty, simple(Adjust::NeverToAny))
} else {
Expand Down Expand Up @@ -510,7 +511,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
// We only have the latter, so we use an inference variable
// for the former and let type inference do the rest.
let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
let coerce_target = self.next_ty_var(origin);
let coerce_target = self.next_ty_var(ty::UniverseIndex::ROOT, origin);
let mut coercion = self.unify_and(coerce_target, target, |target| {
let unsize = Adjustment {
kind: Adjust::Unsize,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(

let drop_impl_span = tcx.def_span(drop_impl_did);
let fresh_impl_substs =
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
infcx.fresh_substs_for_item(ty::UniverseIndex::ROOT, drop_impl_span, drop_impl_did);
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);

let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id);
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_typeck/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
// the process we will unify the transformed-self-type
// of the method with the actual type in order to
// unify some of these variables.
self.fresh_substs_for_item(self.span, trait_def_id)
self.fresh_substs_for_item(ty::UniverseIndex::ROOT, self.span, trait_def_id)
}

probe::WhereClausePick(ref poly_trait_ref) => {
Expand Down Expand Up @@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
{
self.to_ty(ast_ty)
} else {
self.type_var_for_def(self.span, def)
self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def)
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/method/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
} else if let Some(ref input_types) = opt_input_types {
input_types[def.index as usize - 1]
} else {
self.type_var_for_def(span, def)
self.type_var_for_def(ty::UniverseIndex::ROOT, span, def)
}
});

Expand Down
Loading

0 comments on commit 13efaf0

Please sign in to comment.