use middle::region;
use middle::lang_items;
use mir::tcx::PlaceTy;
-use ty::subst::{Kind, Subst, Substs};
+use ty::subst::Substs;
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
-use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
+use ty::fold::TypeFoldable;
use ty::relate::RelateResult;
-use traits::{self, ObligationCause, PredicateObligations, Reveal};
-use rustc_data_structures::unify::{self, UnificationTable};
+use traits::{self, ObligationCause, PredicateObligations};
+use rustc_data_structures::unify as ut;
use std::cell::{Cell, RefCell, Ref, RefMut};
use std::collections::BTreeMap;
use std::fmt;
pub type_variables: RefCell<type_variable::TypeVariableTable<'tcx>>,
// Map from integral variable to the kind of integer it represents
- int_unification_table: RefCell<UnificationTable<ty::IntVid>>,
+ int_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::IntVid>>>,
// Map from floating variable to the kind of float it represents
- float_unification_table: RefCell<UnificationTable<ty::FloatVid>>,
+ float_unification_table: RefCell<ut::UnificationTable<ut::InPlace<ty::FloatVid>>>,
// Tracks the set of region variables and the constraints between
// them. This is initially `Some(_)` but when
#[derive(Clone, Debug)]
pub enum ValuePairs<'tcx> {
Types(ExpectedFound<Ty<'tcx>>),
+ Regions(ExpectedFound<ty::Region<'tcx>>),
TraitRefs(ExpectedFound<ty::TraitRef<'tcx>>),
PolyTraitRefs(ExpectedFound<ty::PolyTraitRef<'tcx>>),
}
in_progress_tables,
projection_cache: RefCell::new(traits::ProjectionCache::new()),
type_variables: RefCell::new(type_variable::TypeVariableTable::new()),
- int_unification_table: RefCell::new(UnificationTable::new()),
- float_unification_table: RefCell::new(UnificationTable::new()),
+ int_unification_table: RefCell::new(ut::UnificationTable::new()),
+ float_unification_table: RefCell::new(ut::UnificationTable::new()),
region_constraints: RefCell::new(Some(RegionConstraintCollector::new())),
lexical_region_resolutions: RefCell::new(None),
selection_cache: traits::SelectionCache::new(),
#[must_use = "once you start a snapshot, you should always consume it"]
pub struct CombinedSnapshot<'a, 'tcx:'a> {
projection_cache_snapshot: traits::ProjectionCacheSnapshot,
- type_snapshot: type_variable::Snapshot,
- int_snapshot: unify::Snapshot<ty::IntVid>,
- float_snapshot: unify::Snapshot<ty::FloatVid>,
+ type_snapshot: type_variable::Snapshot<'tcx>,
+ int_snapshot: ut::Snapshot<ut::InPlace<ty::IntVid>>,
+ float_snapshot: ut::Snapshot<ut::InPlace<ty::FloatVid>>,
region_constraints_snapshot: RegionSnapshot,
region_obligations_snapshot: usize,
was_in_snapshot: bool,
/// Helper trait for shortening the lifetimes inside a
/// value for post-type-checking normalization.
+///
+/// This trait offers a normalization method where the inputs and
+/// outputs both have the `'gcx` lifetime; the implementations
+/// internally create inference contexts and/or lift as needed.
pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
fn trans_normalize<'a, 'tcx>(&self,
infcx: &InferCtxt<'a, 'gcx, 'tcx>,
{
debug!("fully_normalize_associated_types_in(t={:?})", value);
- let param_env = ty::ParamEnv::empty(Reveal::All);
+ let param_env = ty::ParamEnv::reveal_all();
let value = self.erase_regions(value);
if !value.has_projections() {
}
self.infer_ctxt().enter(|infcx| {
- value.trans_normalize(&infcx, env.reveal_all())
+ value.trans_normalize(&infcx, env.with_reveal_all())
})
}
}
use ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
match ty.sty {
ty::TyInfer(ty::IntVar(vid)) => {
- if self.int_unification_table.borrow_mut().has_value(vid) {
+ if self.int_unification_table.borrow_mut().probe_value(vid).is_some() {
Neither
} else {
UnconstrainedInt
}
},
ty::TyInfer(ty::FloatVar(vid)) => {
- if self.float_unification_table.borrow_mut().has_value(vid) {
+ if self.float_unification_table.borrow_mut().probe_value(vid).is_some() {
Neither
} else {
UnconstrainedFloat
}
}
- /// Returns a type variable's default fallback if any exists. A default
- /// must be attached to the variable when created, if it is created
- /// without a default, this will return None.
- ///
- /// This code does not apply to integral or floating point variables,
- /// only to use declared defaults.
- ///
- /// See `new_ty_var_with_default` to create a type variable with a default.
- /// See `type_variable::Default` for details about what a default entails.
- pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
- match ty.sty {
- ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid),
- _ => None
- }
- }
-
pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
let mut variables = Vec::new();
- let unbound_ty_vars = self.type_variables
- .borrow_mut()
- .unsolved_variables()
- .into_iter()
- .map(|t| self.tcx.mk_var(t));
-
- let unbound_int_vars = self.int_unification_table
- .borrow_mut()
- .unsolved_variables()
- .into_iter()
- .map(|v| self.tcx.mk_int_var(v));
+ {
+ let mut type_variables = self.type_variables.borrow_mut();
+ variables.extend(
+ type_variables
+ .unsolved_variables()
+ .into_iter()
+ .map(|t| self.tcx.mk_var(t)));
+ }
- let unbound_float_vars = self.float_unification_table
- .borrow_mut()
- .unsolved_variables()
- .into_iter()
- .map(|v| self.tcx.mk_float_var(v));
+ {
+ let mut int_unification_table = self.int_unification_table.borrow_mut();
+ variables.extend(
+ (0..int_unification_table.len())
+ .map(|i| ty::IntVid { index: i as u32 })
+ .filter(|&vid| int_unification_table.probe_value(vid).is_none())
+ .map(|v| self.tcx.mk_int_var(v)));
+ }
- variables.extend(unbound_ty_vars);
- variables.extend(unbound_int_vars);
- variables.extend(unbound_float_vars);
+ {
+ let mut float_unification_table = self.float_unification_table.borrow_mut();
+ variables.extend(
+ (0..float_unification_table.len())
+ .map(|i| ty::FloatVid { index: i as u32 })
+ .filter(|&vid| float_unification_table.probe_value(vid).is_none())
+ .map(|v| self.tcx.mk_float_var(v)));
+ }
return variables;
}
result
}
- fn start_snapshot<'b>(&'b self) -> CombinedSnapshot<'b, 'tcx> {
+ fn start_snapshot(&self) -> CombinedSnapshot<'a, 'tcx> {
debug!("start_snapshot()");
let in_snapshot = self.in_snapshot.get();
}
}
- fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) {
+ fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot<'a, 'tcx>) {
debug!("rollback_to(cause={})", cause);
let CombinedSnapshot { projection_cache_snapshot,
type_snapshot,
.rollback_to(region_constraints_snapshot);
}
- fn commit_from(&self, snapshot: CombinedSnapshot) {
+ fn commit_from(&self, snapshot: CombinedSnapshot<'a, 'tcx>) {
debug!("commit_from()");
let CombinedSnapshot { projection_cache_snapshot,
type_snapshot,
/// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`
pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
- F: FnOnce(&CombinedSnapshot) -> Result<T, E>
+ F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result<T, E>
{
debug!("commit_if_ok()");
let snapshot = self.start_snapshot();
// Execute `f` in a snapshot, and commit the bindings it creates
pub fn in_snapshot<T, F>(&self, f: F) -> T where
- F: FnOnce(&CombinedSnapshot) -> T
+ F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T
{
debug!("in_snapshot()");
let snapshot = self.start_snapshot();
/// Execute `f` then unroll any bindings it creates
pub fn probe<R, F>(&self, f: F) -> R where
- F: FnOnce(&CombinedSnapshot) -> R,
+ F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R,
{
debug!("probe()");
let snapshot = self.start_snapshot();
self.borrow_region_constraints().make_subregion(origin, a, b);
}
- pub fn equality_predicate(&self,
- cause: &ObligationCause<'tcx>,
- param_env: ty::ParamEnv<'tcx>,
- predicate: &ty::PolyEquatePredicate<'tcx>)
- -> InferResult<'tcx, ()>
- {
- self.commit_if_ok(|snapshot| {
- let (ty::EquatePredicate(a, b), skol_map) =
- self.skolemize_late_bound_regions(predicate, snapshot);
- let cause_span = cause.span;
- let eqty_ok = self.at(cause, param_env).eq(b, a)?;
- self.leak_check(false, cause_span, &skol_map, snapshot)?;
- self.pop_skolemized(skol_map, snapshot);
- Ok(eqty_ok.unit())
- })
- }
-
pub fn subtype_predicate(&self,
cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'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, None)
+ .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 {
/// 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,
- substs: &[Kind<'tcx>])
+ def: &ty::TypeParameterDef)
-> Ty<'tcx> {
- let default = if def.has_default {
- let default = self.tcx.type_of(def.def_id);
- Some(type_variable::Default {
- ty: default.subst_spanned(self.tcx, substs, Some(span)),
- origin_span: span,
- def_id: def.def_id
- })
- } else {
- None
- };
-
-
let ty_var_id = self.type_variables
.borrow_mut()
- .new_var(false,
- TypeVariableOrigin::TypeParameterDefinition(span, def.name),
- default);
+ .new_var(universe,
+ false,
+ TypeVariableOrigin::TypeParameterDefinition(span, def.name));
self.tcx.mk_var(ty_var_id)
}
/// 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, substs| {
- self.type_var_for_def(span, def, substs)
+ }, |def, _| {
+ self.type_var_for_def(universe, span, def)
})
}
// it can be resolved to an int/float variable, which
// can then be recursively resolved, hence the
// recursion. Note though that we prevent type
- // variables from unifying to other type variables
+ // variables from unifyxing to other type variables
// directly (though they may be embedded
// structurally), and we prevent cycles in any case,
// so this recursion should always be of very limited
// depth.
self.type_variables.borrow_mut()
- .probe(v)
- .map(|t| self.shallow_resolve(t))
- .unwrap_or(typ)
+ .probe(v)
+ .known()
+ .map(|t| self.shallow_resolve(t))
+ .unwrap_or(typ)
}
ty::TyInfer(ty::IntVar(v)) => {
self.int_unification_table
.borrow_mut()
- .probe(v)
+ .probe_value(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ)
}
ty::TyInfer(ty::FloatVar(v)) => {
self.float_unification_table
.borrow_mut()
- .probe(v)
+ .probe_value(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ)
}
self.report_and_explain_type_error(trace, &err)
}
- pub fn report_conflicting_default_types(&self,
- span: Span,
- body_id: ast::NodeId,
- expected: type_variable::Default<'tcx>,
- actual: type_variable::Default<'tcx>) {
- let trace = TypeTrace {
- cause: ObligationCause::misc(span, body_id),
- values: Types(ExpectedFound {
- expected: expected.ty,
- found: actual.ty
- })
- };
-
- self.report_and_explain_type_error(
- trace,
- &TypeError::TyParamDefaultMismatch(ExpectedFound {
- expected,
- found: actual
- }))
- .emit();
- }
-
pub fn replace_late_bound_regions_with_fresh_var<T>(
&self,
span: Span,
}
}
-impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- match *self {
- ValuePairs::Types(ref ef) => {
- ValuePairs::Types(ef.fold_with(folder))
- }
- ValuePairs::TraitRefs(ref ef) => {
- ValuePairs::TraitRefs(ef.fold_with(folder))
- }
- ValuePairs::PolyTraitRefs(ref ef) => {
- ValuePairs::PolyTraitRefs(ef.fold_with(folder))
- }
- }
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- match *self {
- ValuePairs::Types(ref ef) => ef.visit_with(visitor),
- ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor),
- ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor),
- }
- }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> {
- fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
- TypeTrace {
- cause: self.cause.fold_with(folder),
- values: self.values.fold_with(folder)
- }
- }
-
- fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
- self.cause.visit_with(visitor) || self.values.visit_with(visitor)
+EnumTypeFoldableImpl! {
+ impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
+ (ValuePairs::Types)(a),
+ (ValuePairs::Regions)(a),
+ (ValuePairs::TraitRefs)(a),
+ (ValuePairs::PolyTraitRefs)(a),
}
}