提交 ddfbf2b0 编写于 作者: B bors

Auto merge of #47861 - sgrif:sg-rebase-chalkify-universe-refactorings, r=nikomatsakis

Rebased refactorings for Chalk

The code is Niko's, I just handled the rebase.

r? @nikomatsakis
......@@ -598,6 +598,14 @@ name = "either"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ena"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "endian-type"
version = "0.1.2"
......@@ -1866,6 +1874,7 @@ name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -2861,6 +2870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
"checksum duct 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e45aa15fe0a8a8f511e6d834626afd55e49b62e5c8802e18328a87e8a8f6065c"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum ena 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1733e41a3c37b0893685933d09dcb0c30269aa5d14dc5cafebf4bcded1e58225"
"checksum endian-type 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
......
......@@ -870,6 +870,7 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for!(struct ty::ParamEnv<'tcx> {
caller_bounds,
universe,
reveal
});
......@@ -1039,3 +1040,12 @@ fn hash_stable<W: StableHasherResult>(&self,
nested.hash_stable(hcx, hasher);
}
}
impl<'gcx> HashStable<StableHashingContext<'gcx>>
for ty::UniverseIndex {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
self.depth().hash_stable(hcx, hasher);
}
}
......@@ -600,7 +600,8 @@ fn fold_anon_ty(
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);
......
......@@ -34,10 +34,10 @@
use super::equate::Equate;
use super::glb::Glb;
use super::{InferCtxt, MiscVariable, TypeTrace};
use super::lub::Lub;
use super::sub::Sub;
use super::InferCtxt;
use super::{MiscVariable, TypeTrace};
use super::type_variable::TypeVariableValue;
use hir::def_id::DefId;
use ty::{IntType, UintType};
......@@ -132,7 +132,7 @@ fn unify_integral_variable(&self,
{
self.int_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.unify_var_value(vid, Some(val))
.map_err(|e| int_unification_error(vid_is_expected, e))?;
match val {
IntType(v) => Ok(self.tcx.mk_mach_int(v)),
......@@ -148,7 +148,7 @@ fn unify_float_variable(&self,
{
self.float_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.unify_var_value(vid, Some(ty::FloatVarValue(val)))
.map_err(|e| float_unification_error(vid_is_expected, e))?;
Ok(self.tcx.mk_mach_float(val))
}
......@@ -194,7 +194,7 @@ pub fn instantiate(&mut self,
use self::RelationDir::*;
// Get the actual variable that b_vid has been inferred to
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_none());
debug_assert!(self.infcx.type_variables.borrow_mut().probe(b_vid).is_unknown());
debug!("instantiate(a_ty={:?} dir={:?} b_vid={:?})", a_ty, dir, b_vid);
......@@ -402,12 +402,12 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
// `vid` are related via subtyping.
return Err(TypeError::CyclicTy(self.root_ty));
} else {
match variables.probe_root(vid) {
Some(u) => {
match variables.probe(vid) {
TypeVariableValue::Known { value: u } => {
drop(variables);
self.relate(&u, &u)
}
None => {
TypeVariableValue::Unknown { universe } => {
match self.ambient_variance {
// Invariant: no need to make a fresh type variable.
ty::Invariant => return Ok(t),
......@@ -423,8 +423,8 @@ fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
ty::Covariant | ty::Contravariant => (),
}
let origin = variables.origin(vid);
let new_var_id = variables.new_var(false, origin, None);
let origin = *variables.var_origin(vid);
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);
......@@ -518,9 +518,9 @@ fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::Int
}
fn float_unification_error<'tcx>(a_is_expected: bool,
v: (ast::FloatTy, ast::FloatTy))
v: (ty::FloatVarValue, ty::FloatVarValue))
-> TypeError<'tcx>
{
let (a, b) = v;
let (ty::FloatVarValue(a), ty::FloatVarValue(b)) = v;
TypeError::FloatMismatch(ty::relate::expected_found_bool(a_is_expected, &a, &b))
}
......@@ -133,7 +133,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match t.sty {
ty::TyInfer(ty::TyVar(v)) => {
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v);
let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known();
self.freshen(
opt_ty,
ty::TyVar(v),
......@@ -143,7 +143,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
ty::TyInfer(ty::IntVar(v)) => {
self.freshen(
self.infcx.int_unification_table.borrow_mut()
.probe(v)
.probe_value(v)
.map(|v| v.to_type(tcx)),
ty::IntVar(v),
ty::FreshIntTy)
......@@ -152,7 +152,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
ty::TyInfer(ty::FloatVar(v)) => {
self.freshen(
self.infcx.float_unification_table.borrow_mut()
.probe(v)
.probe_value(v)
.map(|v| v.to_type(tcx)),
ty::FloatVar(v),
ty::FreshFloatTy)
......
......@@ -131,7 +131,9 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
// variables to their binding anyhow, we know
// that it is unbound, so we can just return
// it.
debug_assert!(self.infcx.type_variables.borrow_mut().probe(vid).is_none());
debug_assert!(self.infcx.type_variables.borrow_mut()
.probe(vid)
.is_unknown());
ty
}
......@@ -139,7 +141,11 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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)
}
}
}
......
......@@ -244,7 +244,7 @@ pub fn higher_ranked_lub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expect
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
span: Span,
snapshot: &CombinedSnapshot,
snapshot: &CombinedSnapshot<'a, 'tcx>,
debruijn: ty::DebruijnIndex,
new_vars: &[ty::RegionVid],
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
......@@ -340,7 +340,7 @@ pub fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expect
fn generalize_region<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
span: Span,
snapshot: &CombinedSnapshot,
snapshot: &CombinedSnapshot<'a, 'tcx>,
debruijn: ty::DebruijnIndex,
new_vars: &[ty::RegionVid],
a_map: &BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
......@@ -479,7 +479,7 @@ fn fold_regions_in<'a, 'gcx, 'tcx, T, F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
fn tainted_regions(&self,
snapshot: &CombinedSnapshot,
snapshot: &CombinedSnapshot<'a, 'tcx>,
r: ty::Region<'tcx>,
directions: TaintDirections)
-> FxHashSet<ty::Region<'tcx>> {
......@@ -491,7 +491,7 @@ fn tainted_regions(&self,
}
fn region_vars_confined_to_snapshot(&self,
snapshot: &CombinedSnapshot)
snapshot: &CombinedSnapshot<'a, 'tcx>)
-> Vec<ty::RegionVid>
{
/*!
......@@ -583,7 +583,7 @@ fn region_vars_confined_to_snapshot(&self,
/// See `README.md` for more details.
pub fn skolemize_late_bound_regions<T>(&self,
binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot)
snapshot: &CombinedSnapshot<'a, 'tcx>)
-> (T, SkolemizationMap<'tcx>)
where T : TypeFoldable<'tcx>
{
......@@ -609,7 +609,7 @@ pub fn leak_check(&self,
overly_polymorphic: bool,
_span: Span,
skol_map: &SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot)
snapshot: &CombinedSnapshot<'a, 'tcx>)
-> RelateResult<'tcx, ()>
{
debug!("leak_check: skol_map={:?}",
......@@ -684,7 +684,7 @@ pub fn leak_check(&self,
/// predicate is `for<'a> &'a int : Clone`.
pub fn plug_leaks<T>(&self,
skol_map: SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot,
snapshot: &CombinedSnapshot<'a, 'tcx>,
value: T) -> T
where T : TypeFoldable<'tcx>
{
......@@ -770,8 +770,7 @@ pub fn plug_leaks<T>(&self,
/// Note: popping also occurs implicitly as part of `leak_check`.
pub fn pop_skolemized(&self,
skol_map: SkolemizationMap<'tcx>,
snapshot: &CombinedSnapshot)
{
snapshot: &CombinedSnapshot<'a, 'tcx>) {
debug!("pop_skolemized({:?})", skol_map);
let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect();
self.borrow_region_constraints()
......
......@@ -70,14 +70,6 @@ pub fn super_lattice_tys<'a, 'gcx, 'tcx, L>(this: &mut L,
let a = infcx.type_variables.borrow_mut().replace_if_possible(a);
let b = infcx.type_variables.borrow_mut().replace_if_possible(b);
match (&a.sty, &b.sty) {
(&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..)))
if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
let v = infcx.next_diverging_ty_var(
TypeVariableOrigin::LatticeVariable(this.cause().span));
this.relate_bound(v, a, b)?;
Ok(v)
}
// If one side is known to be a variable and one is not,
// create a variable (`v`) to represent the LUB. Make sure to
// relate `v` to the non-type-variable first (by passing it
......@@ -96,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)
}
......
......@@ -22,14 +22,14 @@
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::relate::RelateResult;
use traits::{self, ObligationCause, PredicateObligations, Reveal};
use rustc_data_structures::unify::{self, UnificationTable};
use rustc_data_structures::unify as ut;
use std::cell::{Cell, RefCell, Ref, RefMut};
use std::collections::BTreeMap;
use std::fmt;
......@@ -99,10 +99,10 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
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
......@@ -441,8 +441,8 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
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(),
......@@ -475,9 +475,9 @@ pub fn unit(self) -> InferOk<'tcx, ()> {
#[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,
......@@ -678,14 +678,14 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
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
......@@ -695,46 +695,35 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
}
}
/// 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;
}
......@@ -776,7 +765,7 @@ pub fn save_and_restore_in_snapshot_flag<F, R>(&self, func: F) -> R
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();
......@@ -798,7 +787,7 @@ fn start_snapshot<'b>(&'b self) -> CombinedSnapshot<'b, 'tcx> {
}
}
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,
......@@ -830,7 +819,7 @@ fn rollback_to(&self, cause: &str, snapshot: CombinedSnapshot) {
.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,
......@@ -872,7 +861,7 @@ pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
/// 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();
......@@ -887,7 +876,7 @@ pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
// 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();
......@@ -898,7 +887,7 @@ pub fn in_snapshot<T, F>(&self, f: F) -> T where
/// 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();
......@@ -1026,18 +1015,25 @@ pub fn region_outlives_predicate(&self,
})
}
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 {
......@@ -1092,27 +1088,15 @@ pub fn region_var_for_def(&self,
/// 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)
}
......@@ -1120,13 +1104,14 @@ pub fn type_var_for_def(&self,
/// 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)
})
}
......@@ -1284,15 +1269,16 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
// 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)
}
......@@ -1300,7 +1286,7 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
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)
}
......@@ -1402,28 +1388,6 @@ pub fn report_mismatched_types(&self,
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,
......
......@@ -18,7 +18,7 @@
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::unify::{self, UnificationTable};
use rustc_data_structures::unify as ut;
use ty::{self, Ty, TyCtxt};
use ty::{Region, RegionVid};
use ty::ReStatic;
......@@ -48,7 +48,7 @@ pub struct RegionConstraintCollector<'tcx> {
glbs: CombineMap<'tcx>,
/// Number of skolemized variables currently active.
skolemization_count: u32,
skolemization_count: ty::UniverseIndex,
/// Global counter used during the GLB algorithm to create unique
/// names for fresh bound regions
......@@ -73,7 +73,7 @@ pub struct RegionConstraintCollector<'tcx> {
/// is iterating to a fixed point, because otherwise we sometimes
/// would wind up with a fresh stream of region variables that
/// have been equated but appear distinct.
unification_table: UnificationTable<ty::RegionVid>,
unification_table: ut::UnificationTable<ut::InPlace<ty::RegionVid>>,
}
pub type VarOrigins = IndexVec<RegionVid, RegionVariableOrigin>;
......@@ -232,8 +232,8 @@ enum CombineMapType {
pub struct RegionSnapshot {
length: usize,
region_snapshot: unify::Snapshot<ty::RegionVid>,
skolemization_count: u32,
region_snapshot: ut::Snapshot<ut::InPlace<ty::RegionVid>>,
skolemization_count: ty::UniverseIndex,
}
/// When working with skolemized regions, we often wish to find all of
......@@ -277,10 +277,10 @@ pub fn new() -> RegionConstraintCollector<'tcx> {
data: RegionConstraintData::default(),
lubs: FxHashMap(),
glbs: FxHashMap(),
skolemization_count: 0,
skolemization_count: ty::UniverseIndex::ROOT,
bound_count: 0,
undo_log: Vec::new(),
unification_table: UnificationTable::new(),
unification_table: ut::UnificationTable::new(),
}
}
......@@ -329,7 +329,7 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
unification_table,
} = self;
assert_eq!(*skolemization_count, 0);
assert_eq!(skolemization_count.as_usize(), 0);
// Clear the tables of (lubs, glbs), so that we will create
// fresh regions if we do a LUB operation. As it happens,
......@@ -342,7 +342,7 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
// un-unified" state. Note that when we unify `a` and `b`, we
// also insert `a <= b` and a `b <= a` edges, so the
// `RegionConstraintData` contains the relationship here.
*unification_table = UnificationTable::new();
*unification_table = ut::UnificationTable::new();
for vid in var_origins.indices() {
unification_table.new_key(unify_key::RegionVidKey { min_vid: vid });
}
......@@ -371,7 +371,7 @@ pub fn commit(&mut self, snapshot: RegionSnapshot) {
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
assert!(
self.skolemization_count == snapshot.skolemization_count,
"failed to pop skolemized regions: {} now vs {} at start",
"failed to pop skolemized regions: {:?} now vs {:?} at start",
self.skolemization_count,
snapshot.skolemization_count
);
......@@ -479,9 +479,9 @@ pub fn push_skolemized(
assert!(self.in_snapshot());
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
let sc = self.skolemization_count;
self.skolemization_count = sc + 1;
tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br))
let universe = self.skolemization_count.subuniverse();
self.skolemization_count = universe;
tcx.mk_region(ReSkolemized(universe, br))
}
/// Removes all the edges to/from the skolemized regions that are
......@@ -499,20 +499,20 @@ pub fn pop_skolemized(
assert!(self.in_snapshot());
assert!(self.undo_log[snapshot.length] == OpenSnapshot);
assert!(
self.skolemization_count as usize >= skols.len(),
self.skolemization_count.as_usize() >= skols.len(),
"popping more skolemized variables than actually exist, \
sc now = {}, skols.len = {}",
self.skolemization_count,
self.skolemization_count.as_usize(),
skols.len()
);
let last_to_pop = self.skolemization_count;
let first_to_pop = last_to_pop - (skols.len() as u32);
let last_to_pop = self.skolemization_count.subuniverse();
let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - (skols.len() as u32));
assert!(
first_to_pop >= snapshot.skolemization_count,
"popping more regions than snapshot contains, \
sc now = {}, sc then = {}, skols.len = {}",
sc now = {:?}, sc then = {:?}, skols.len = {}",
self.skolemization_count,
snapshot.skolemization_count,
skols.len()
......@@ -520,13 +520,13 @@ pub fn pop_skolemized(
debug_assert! {
skols.iter()
.all(|&k| match *k {
ty::ReSkolemized(index, _) =>
index.index >= first_to_pop &&
index.index < last_to_pop,
ty::ReSkolemized(universe, _) =>
universe >= first_to_pop &&
universe < last_to_pop,
_ =>
false
}),
"invalid skolemization keys or keys out of range ({}..{}): {:?}",
"invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}",
snapshot.skolemization_count,
self.skolemization_count,
skols
......@@ -776,7 +776,7 @@ pub fn opportunistic_resolve_var(
tcx: TyCtxt<'_, '_, 'tcx>,
rid: RegionVid,
) -> ty::Region<'tcx> {
let vid = self.unification_table.find_value(rid).min_vid;
let vid = self.unification_table.probe_value(rid).min_vid;
tcx.mk_region(ty::ReVar(vid))
}
......@@ -861,7 +861,7 @@ impl fmt::Debug for RegionSnapshot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"RegionSnapshot(length={},skolemization={})",
"RegionSnapshot(length={},skolemization={:?})",
self.length,
self.skolemization_count
)
......
此差异已折叠。
......@@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syntax::ast;
use ty::{self, IntVarValue, Ty, TyCtxt};
use rustc_data_structures::unify::{Combine, UnifyKey};
use ty::{self, FloatVarValue, IntVarValue, Ty, TyCtxt};
use rustc_data_structures::unify::{NoError, EqUnifyValue, UnifyKey, UnifyValue};
pub trait ToType {
fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>;
......@@ -20,7 +19,10 @@ impl UnifyKey for ty::IntVid {
type Value = Option<IntVarValue>;
fn index(&self) -> u32 { self.index }
fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } }
fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
fn tag() -> &'static str { "IntVid" }
}
impl EqUnifyValue for IntVarValue {
}
#[derive(PartialEq, Copy, Clone, Debug)]
......@@ -31,15 +33,17 @@ pub struct RegionVidKey {
pub min_vid: ty::RegionVid
}
impl Combine for RegionVidKey {
fn combine(&self, other: &RegionVidKey) -> RegionVidKey {
let min_vid = if self.min_vid.index() < other.min_vid.index() {
self.min_vid
impl UnifyValue for RegionVidKey {
type Error = NoError;
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
let min_vid = if value1.min_vid.index() < value2.min_vid.index() {
value1.min_vid
} else {
other.min_vid
value2.min_vid
};
RegionVidKey { min_vid: min_vid }
Ok(RegionVidKey { min_vid: min_vid })
}
}
......@@ -47,7 +51,7 @@ impl UnifyKey for ty::RegionVid {
type Value = RegionVidKey;
fn index(&self) -> u32 { self.0 }
fn from_index(i: u32) -> ty::RegionVid { ty::RegionVid(i) }
fn tag(_: Option<ty::RegionVid>) -> &'static str { "RegionVid" }
fn tag() -> &'static str { "RegionVid" }
}
impl ToType for IntVarValue {
......@@ -62,21 +66,17 @@ fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
// Floating point type keys
impl UnifyKey for ty::FloatVid {
type Value = Option<ast::FloatTy>;
type Value = Option<FloatVarValue>;
fn index(&self) -> u32 { self.index }
fn from_index(i: u32) -> ty::FloatVid { ty::FloatVid { index: i } }
fn tag(_: Option<ty::FloatVid>) -> &'static str { "FloatVid" }
fn tag() -> &'static str { "FloatVid" }
}
impl ToType for ast::FloatTy {
fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
tcx.mk_mach_float(*self)
}
impl EqUnifyValue for FloatVarValue {
}
impl UnifyKey for ty::TyVid {
type Value = ();
fn index(&self) -> u32 { self.index }
fn from_index(i: u32) -> ty::TyVid { ty::TyVid { index: i } }
fn tag(_: Option<ty::TyVid>) -> &'static str { "TyVid" }
impl ToType for FloatVarValue {
fn to_type<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
tcx.mk_mach_float(self.0)
}
}
......@@ -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,
......
......@@ -292,7 +292,9 @@ fn impl_similar_to(&self,
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()
......@@ -1194,6 +1196,7 @@ fn predicate_can_apply(&self,
-> 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>>
}
......@@ -1203,9 +1206,14 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.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)
}
......@@ -1217,6 +1225,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
infcx: self,
param_env,
var_map: FxHashMap()
});
......
......@@ -77,10 +77,21 @@ pub enum IntercrateMode {
/// scope. The eventual result is usually a `Selection` (defined below).
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Obligation<'tcx, T> {
/// Why do we have to prove this thing?
pub cause: ObligationCause<'tcx>,
/// In which environment should we prove this thing?
pub param_env: ty::ParamEnv<'tcx>,
pub recursion_depth: usize,
/// What are we trying to prove?
pub predicate: T,
/// If we started proving this as a result of trying to prove
/// something else, track the total depth to ensure termination.
/// If this goes over a certain threshold, we abort compilation --
/// in such cases, we can not say whether or not the predicate
/// holds for certain. Stupid halting problem. Such a drag.
pub recursion_depth: usize,
}
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
......@@ -535,7 +546,8 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
predicates);
let elaborated_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
unnormalized_env.reveal);
unnormalized_env.reveal,
unnormalized_env.universe);
tcx.infer_ctxt().enter(|infcx| {
// FIXME. We should really... do something with these region
......@@ -609,7 +621,9 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
debug!("normalize_param_env_or_error: resolved predicates={:?}",
predicates);
ty::ParamEnv::new(tcx.intern_predicates(&predicates), unnormalized_env.reveal)
ty::ParamEnv::new(tcx.intern_predicates(&predicates),
unnormalized_env.reveal,
unnormalized_env.universe)
})
}
......
......@@ -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,
......@@ -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,
......
......@@ -496,7 +496,7 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
/// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
/// context's self.
fn in_snapshot<R, F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
{
// The irrefutable nature of the operation means we don't need to snapshot the
// inferred_obligations vector.
......@@ -506,7 +506,7 @@ fn in_snapshot<R, F>(&mut self, f: F) -> R
/// Wraps a probe s.t. obligations collected during it are ignored and old obligations are
/// retained.
fn probe<R, F>(&mut self, f: F) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot) -> R
where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
{
let inferred_obligations_snapshot = self.inferred_obligations.start_snapshot();
let result = self.infcx.probe(|snapshot| f(self, snapshot));
......@@ -1478,7 +1478,7 @@ fn assemble_candidates_from_projected_tys(&mut self,
fn match_projection_obligation_against_definition_bounds(
&mut self,
obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> bool
{
let poly_trait_predicate =
......@@ -1549,7 +1549,7 @@ fn match_projection(&mut self,
trait_bound: ty::PolyTraitRef<'tcx>,
skol_trait_ref: ty::TraitRef<'tcx>,
skol_map: &infer::SkolemizationMap<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> bool
{
assert!(!skol_trait_ref.has_escaping_regions());
......@@ -2587,7 +2587,7 @@ fn vtable_impl(&mut self,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
skol_map: infer::SkolemizationMap<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> VtableImplData<'tcx, PredicateObligation<'tcx>>
{
debug!("vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, skol_map={:?})",
......@@ -3076,7 +3076,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
fn rematch_impl(&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> (Normalized<'tcx, &'tcx Substs<'tcx>>,
infer::SkolemizationMap<'tcx>)
{
......@@ -3093,7 +3093,7 @@ fn rematch_impl(&mut self,
fn match_impl(&mut self,
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> Result<(Normalized<'tcx, &'tcx Substs<'tcx>>,
infer::SkolemizationMap<'tcx>), ()>
{
......@@ -3111,7 +3111,8 @@ fn match_impl(&mut self,
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(),
......@@ -3288,7 +3289,7 @@ fn impl_or_trait_obligations(&mut self,
def_id: DefId, // of impl or trait
substs: &Substs<'tcx>, // for impl or trait
skol_map: infer::SkolemizationMap<'tcx>,
snapshot: &infer::CombinedSnapshot)
snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-> Vec<PredicateObligation<'tcx>>
{
debug!("impl_or_trait_obligations(def_id={:?})", def_id);
......
......@@ -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,
......
......@@ -9,9 +9,8 @@
// except according to those terms.
use hir::def_id::DefId;
use infer::type_variable;
use middle::const_val::ConstVal;
use ty::{self, BoundRegion, DefIdTree, Region, Ty, TyCtxt};
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
use std::fmt;
use syntax::abi;
......@@ -56,7 +55,6 @@ pub enum TypeError<'tcx> {
CyclicTy(Ty<'tcx>),
ProjectionMismatched(ExpectedFound<DefId>),
ProjectionBoundsLength(ExpectedFound<usize>),
TyParamDefaultMismatch(ExpectedFound<type_variable::Default<'tcx>>),
ExistentialMismatch(ExpectedFound<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>>),
OldStyleLUB(Box<TypeError<'tcx>>),
......@@ -167,11 +165,6 @@ fn report_maybe_different(f: &mut fmt::Formatter,
values.expected,
values.found)
},
TyParamDefaultMismatch(ref values) => {
write!(f, "conflicting type parameter defaults `{}` and `{}`",
values.expected.ty,
values.found.ty)
}
ExistentialMismatch(ref values) => {
report_maybe_different(f, format!("trait `{}`", values.expected),
format!("trait `{}`", values.found))
......@@ -265,42 +258,6 @@ pub fn note_and_explain_type_err(self,
db.help("consider boxing your closure and/or using it as a trait object");
}
},
TyParamDefaultMismatch(values) => {
let expected = values.expected;
let found = values.found;
db.span_note(sp, &format!("conflicting type parameter defaults `{}` and `{}`",
expected.ty,
found.ty));
match self.hir.span_if_local(expected.def_id) {
Some(span) => {
db.span_note(span, "a default was defined here...");
}
None => {
let item_def_id = self.parent(expected.def_id).unwrap();
db.note(&format!("a default is defined on `{}`",
self.item_path_str(item_def_id)));
}
}
db.span_note(
expected.origin_span,
"...that was applied to an unconstrained type variable here");
match self.hir.span_if_local(found.def_id) {
Some(span) => {
db.span_note(span, "a second default was defined here...");
}
None => {
let item_def_id = self.parent(found.def_id).unwrap();
db.note(&format!("a second default is defined on `{}`",
self.item_path_str(item_def_id)));
}
}
db.span_note(found.origin_span,
"...that also applies to the same type variable here");
}
OldStyleLUB(err) => {
db.note("this was previously accepted by the compiler but has been phased out");
db.note("for more information, see https://github.com/rust-lang/rust/issues/45852");
......
......@@ -69,7 +69,7 @@
pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
pub use self::sty::RegionKind;
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid};
pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid};
pub use self::sty::BoundRegion::*;
pub use self::sty::InferTy::*;
pub use self::sty::RegionKind::*;
......@@ -685,12 +685,15 @@ pub struct ClosureUpvar<'tcx> {
pub ty: Ty<'tcx>,
}
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum IntVarValue {
IntType(ast::IntTy),
UintType(ast::UintTy),
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct FloatVarValue(pub ast::FloatTy);
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct TypeParameterDef {
pub name: Name,
......@@ -1306,6 +1309,85 @@ pub fn is_empty(&self) -> bool {
}
}
/// "Universes" are used during type- and trait-checking in the
/// presence of `for<..>` binders to control what sets of names are
/// visible. Universes are arranged into a tree: the root universe
/// contains names that are always visible. But when you enter into
/// some subuniverse, then it may add names that are only visible
/// within that subtree (but it can still name the names of its
/// ancestor universes).
///
/// To make this more concrete, consider this program:
///
/// ```
/// struct Foo { }
/// fn bar<T>(x: T) {
/// let y: for<'a> fn(&'a u8, Foo) = ...;
/// }
/// ```
///
/// The struct name `Foo` is in the root universe U0. But the type
/// parameter `T`, introduced on `bar`, is in a subuniverse U1 --
/// i.e., within `bar`, we can name both `T` and `Foo`, but outside of
/// `bar`, we cannot name `T`. Then, within the type of `y`, the
/// region `'a` is in a subuniverse U2 of U1, because we can name it
/// inside the fn type but not outside.
///
/// Universes are related to **skolemization** -- which is a way of
/// doing type- and trait-checking around these "forall" binders (also
/// called **universal quantification**). The idea is that when, in
/// the body of `bar`, we refer to `T` as a type, we aren't referring
/// to any type in particular, but rather a kind of "fresh" type that
/// is distinct from all other types we have actually declared. This
/// is called a **skolemized** type, and we use universes to talk
/// about this. In other words, a type name in universe 0 always
/// corresponds to some "ground" type that the user declared, but a
/// type name in a non-zero universe is a skolemized type -- an
/// idealized representative of "types in general" that we use for
/// checking generic functions.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
pub struct UniverseIndex(u32);
impl UniverseIndex {
/// The root universe, where things that the user defined are
/// visible.
pub const ROOT: UniverseIndex = UniverseIndex(0);
/// A "subuniverse" corresponds to being inside a `forall` quantifier.
/// So, for example, suppose we have this type in universe `U`:
///
/// ```
/// for<'a> fn(&'a u32)
/// ```
///
/// Once we "enter" into this `for<'a>` quantifier, we are in a
/// subuniverse of `U` -- in this new universe, we can name the
/// region `'a`, but that region was not nameable from `U` because
/// it was not in scope there.
pub fn subuniverse(self) -> UniverseIndex {
UniverseIndex(self.0.checked_add(1).unwrap())
}
pub fn from(v: u32) -> UniverseIndex {
UniverseIndex(v)
}
pub fn as_u32(&self) -> u32 {
self.0
}
pub fn as_usize(&self) -> usize {
self.0 as usize
}
/// Gets the "depth" of this universe in the universe tree. This
/// is not really useful except for e.g. the `HashStable`
/// implementation
pub fn depth(&self) -> u32 {
self.0
}
}
/// When type checking, we use the `ParamEnv` to track
/// details about the set of where-clauses that are in scope at this
/// particular point.
......@@ -1320,6 +1402,17 @@ pub struct ParamEnv<'tcx> {
/// want `Reveal::All` -- note that this is always paired with an
/// empty environment. To get that, use `ParamEnv::reveal()`.
pub reveal: traits::Reveal,
/// 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: UniverseIndex,
}
impl<'tcx> ParamEnv<'tcx> {
......@@ -2595,7 +2688,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// sure that this will succeed without errors anyway.
let unnormalized_env = ty::ParamEnv::new(tcx.intern_predicates(&predicates),
traits::Reveal::UserFacing);
traits::Reveal::UserFacing,
ty::UniverseIndex::ROOT);
let body_id = tcx.hir.as_local_node_id(def_id).map_or(DUMMY_NODE_ID, |id| {
tcx.hir.maybe_body_owned_by(id).map_or(id, |body| body.node_id)
......
......@@ -13,7 +13,6 @@
//! hand, though we've recently added some macros (e.g.,
//! `BraceStructLiftImpl!`) to help with the tedium.
use infer::type_variable;
use middle::const_val::{self, ConstVal, ConstAggregate, ConstEvalErr};
use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
......@@ -405,6 +404,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
tcx.lift(&self.caller_bounds).map(|caller_bounds| {
ty::ParamEnv {
reveal: self.reveal,
universe: self.universe,
caller_bounds,
}
})
......@@ -547,13 +547,6 @@ fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lif
}
}
BraceStructLiftImpl! {
impl<'a, 'tcx> Lift<'tcx> for type_variable::Default<'a> {
type Lifted = type_variable::Default<'tcx>;
ty, origin_span, def_id
}
}
impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> {
type Lifted = ty::error::TypeError<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
......@@ -585,11 +578,8 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
Sorts(ref x) => return tcx.lift(x).map(Sorts),
TyParamDefaultMismatch(ref x) => {
return tcx.lift(x).map(TyParamDefaultMismatch)
}
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch),
OldStyleLUB(ref x) => return tcx.lift(x).map(OldStyleLUB),
ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
})
}
}
......@@ -733,8 +723,29 @@ fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
BraceStructTypeFoldableImpl! {
impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> { reveal, caller_bounds }
impl<'tcx> TypeFoldable<'tcx> for ty::ParamEnv<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
ty::ParamEnv {
reveal: self.reveal,
caller_bounds: self.caller_bounds.fold_with(folder),
universe: self.universe.fold_with(folder),
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
let &ty::ParamEnv { reveal: _, ref universe, ref caller_bounds } = self;
universe.super_visit_with(visitor) || caller_bounds.super_visit_with(visitor)
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::UniverseIndex {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
*self
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
false
}
}
impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice<ty::ExistentialPredicate<'tcx>> {
......@@ -1177,20 +1188,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
}
}
impl<'tcx> TypeFoldable<'tcx> for type_variable::Default<'tcx> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
type_variable::Default {
ty: self.ty.fold_with(folder),
origin_span: self.origin_span,
def_id: self.def_id
}
}
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.ty.visit_with(visitor)
}
}
impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
self.iter().map(|x| x.fold_with(folder)).collect()
......@@ -1230,7 +1227,6 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
ProjectionMismatched(x) => ProjectionMismatched(x),
ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
Sorts(x) => Sorts(x.fold_with(folder)),
TyParamDefaultMismatch(ref x) => TyParamDefaultMismatch(x.fold_with(folder)),
ExistentialMismatch(x) => ExistentialMismatch(x.fold_with(folder)),
OldStyleLUB(ref x) => OldStyleLUB(x.fold_with(folder)),
}
......@@ -1251,7 +1247,6 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
},
Sorts(x) => x.visit_with(visitor),
OldStyleLUB(ref x) => x.visit_with(visitor),
TyParamDefaultMismatch(ref x) => x.visit_with(visitor),
ExistentialMismatch(x) => x.visit_with(visitor),
CyclicTy(t) => t.visit_with(visitor),
Mismatch |
......
......@@ -1028,7 +1028,7 @@ pub enum RegionKind {
/// A skolemized region - basically the higher-ranked version of ReFree.
/// Should not exist after typeck.
ReSkolemized(SkolemizedRegionVid, BoundRegion),
ReSkolemized(ty::UniverseIndex, BoundRegion),
/// Empty lifetime is for data that is never accessed.
/// Bottom in the region lattice. We treat ReEmpty somewhat
......@@ -1079,11 +1079,6 @@ pub struct FloatVid {
DEBUG_FORMAT = custom,
});
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
pub struct SkolemizedRegionVid {
pub index: u32,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum InferTy {
TyVar(TyVid),
......
......@@ -153,14 +153,15 @@ impl<'tcx> ty::ParamEnv<'tcx> {
/// Construct a trait environment suitable for contexts where
/// there are no where clauses in scope.
pub fn empty(reveal: Reveal) -> Self {
Self::new(ty::Slice::empty(), reveal)
Self::new(ty::Slice::empty(), reveal, ty::UniverseIndex::ROOT)
}
/// Construct a trait environment with the given set of predicates.
pub fn new(caller_bounds: &'tcx ty::Slice<ty::Predicate<'tcx>>,
reveal: Reveal)
reveal: Reveal,
universe: ty::UniverseIndex)
-> Self {
ty::ParamEnv { caller_bounds, reveal }
ty::ParamEnv { caller_bounds, reveal, universe }
}
/// Returns a new parameter environment with the same clauses, but
......
......@@ -786,7 +786,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
ty::ReSkolemized(id, ref bound_region) => {
write!(f, "ReSkolemized({}, {:?})", id.index, bound_region)
write!(f, "ReSkolemized({:?}, {:?})", id, bound_region)
}
ty::ReEmpty => write!(f, "ReEmpty"),
......@@ -916,6 +916,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
impl fmt::Debug for ty::FloatVarValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
// The generic impl doesn't work yet because projections are not
// normalized under HRTB.
/*impl<T> fmt::Display for ty::Binder<T>
......
......@@ -9,6 +9,7 @@ path = "lib.rs"
crate-type = ["dylib"]
[dependencies]
ena = "0.9.1"
log = "0.4"
serialize = { path = "../libserialize" }
cfg-if = "0.1.2"
......
......@@ -39,6 +39,7 @@
#![cfg_attr(test, feature(test))]
extern crate core;
extern crate ena;
#[macro_use]
extern crate log;
extern crate serialize as rustc_serialize; // used by deriving
......@@ -63,10 +64,10 @@
pub mod obligation_forest;
pub mod sip128;
pub mod snapshot_map;
pub mod snapshot_vec;
pub use ena::snapshot_vec;
pub mod stable_hasher;
pub mod transitive_relation;
pub mod unify;
pub use ena::unify;
pub mod fx;
pub mod tuple_slice;
pub mod control_flow_graph;
......
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A utility class for implementing "snapshottable" things; a snapshottable data structure permits
//! you to take a snapshot (via `start_snapshot`) and then, after making some changes, elect either
//! to rollback to the start of the snapshot or commit those changes.
//!
//! This vector is intended to be used as part of an abstraction, not serve as a complete
//! abstraction on its own. As such, while it will roll back most changes on its own, it also
//! supports a `get_mut` operation that gives you an arbitrary mutable pointer into the vector. To
//! ensure that any changes you make this with this pointer are rolled back, you must invoke
//! `record` to record any changes you make and also supplying a delegate capable of reversing
//! those changes.
use self::UndoLog::*;
use std::mem;
use std::ops;
pub enum UndoLog<D: SnapshotVecDelegate> {
/// Indicates where a snapshot started.
OpenSnapshot,
/// Indicates a snapshot that has been committed.
CommittedSnapshot,
/// New variable with given index was created.
NewElem(usize),
/// Variable with given index was changed *from* the given value.
SetElem(usize, D::Value),
/// Extensible set of actions
Other(D::Undo),
}
pub struct SnapshotVec<D: SnapshotVecDelegate> {
values: Vec<D::Value>,
undo_log: Vec<UndoLog<D>>,
}
// Snapshots are tokens that should be created/consumed linearly.
pub struct Snapshot {
// Length of the undo log at the time the snapshot was taken.
length: usize,
}
pub trait SnapshotVecDelegate {
type Value;
type Undo;
fn reverse(values: &mut Vec<Self::Value>, action: Self::Undo);
}
impl<D: SnapshotVecDelegate> SnapshotVec<D> {
pub fn new() -> SnapshotVec<D> {
SnapshotVec {
values: Vec::new(),
undo_log: Vec::new(),
}
}
pub fn with_capacity(n: usize) -> SnapshotVec<D> {
SnapshotVec {
values: Vec::with_capacity(n),
undo_log: Vec::new(),
}
}
fn in_snapshot(&self) -> bool {
!self.undo_log.is_empty()
}
pub fn record(&mut self, action: D::Undo) {
if self.in_snapshot() {
self.undo_log.push(Other(action));
}
}
pub fn len(&self) -> usize {
self.values.len()
}
pub fn push(&mut self, elem: D::Value) -> usize {
let len = self.values.len();
self.values.push(elem);
if self.in_snapshot() {
self.undo_log.push(NewElem(len));
}
len
}
pub fn get(&self, index: usize) -> &D::Value {
&self.values[index]
}
/// Returns a mutable pointer into the vec; whatever changes you make here cannot be undone
/// automatically, so you should be sure call `record()` with some sort of suitable undo
/// action.
pub fn get_mut(&mut self, index: usize) -> &mut D::Value {
&mut self.values[index]
}
/// Updates the element at the given index. The old value will saved (and perhaps restored) if
/// a snapshot is active.
pub fn set(&mut self, index: usize, new_elem: D::Value) {
let old_elem = mem::replace(&mut self.values[index], new_elem);
if self.in_snapshot() {
self.undo_log.push(SetElem(index, old_elem));
}
}
pub fn start_snapshot(&mut self) -> Snapshot {
let length = self.undo_log.len();
self.undo_log.push(OpenSnapshot);
Snapshot { length: length }
}
pub fn actions_since_snapshot(&self, snapshot: &Snapshot) -> &[UndoLog<D>] {
&self.undo_log[snapshot.length..]
}
fn assert_open_snapshot(&self, snapshot: &Snapshot) {
// Or else there was a failure to follow a stack discipline:
assert!(self.undo_log.len() > snapshot.length);
// Invariant established by start_snapshot():
assert!(match self.undo_log[snapshot.length] {
OpenSnapshot => true,
_ => false,
});
}
pub fn rollback_to(&mut self, snapshot: Snapshot) {
debug!("rollback_to({})", snapshot.length);
self.assert_open_snapshot(&snapshot);
while self.undo_log.len() > snapshot.length + 1 {
match self.undo_log.pop().unwrap() {
OpenSnapshot => {
// This indicates a failure to obey the stack discipline.
panic!("Cannot rollback an uncommitted snapshot");
}
CommittedSnapshot => {
// This occurs when there are nested snapshots and
// the inner is committed but outer is rolled back.
}
NewElem(i) => {
self.values.pop();
assert!(self.values.len() == i);
}
SetElem(i, v) => {
self.values[i] = v;
}
Other(u) => {
D::reverse(&mut self.values, u);
}
}
}
let v = self.undo_log.pop().unwrap();
assert!(match v {
OpenSnapshot => true,
_ => false,
});
assert!(self.undo_log.len() == snapshot.length);
}
/// Commits all changes since the last snapshot. Of course, they
/// can still be undone if there is a snapshot further out.
pub fn commit(&mut self, snapshot: Snapshot) {
debug!("commit({})", snapshot.length);
self.assert_open_snapshot(&snapshot);
if snapshot.length == 0 {
// The root snapshot.
self.undo_log.truncate(0);
} else {
self.undo_log[snapshot.length] = CommittedSnapshot;
}
}
}
impl<D: SnapshotVecDelegate> ops::Deref for SnapshotVec<D> {
type Target = [D::Value];
fn deref(&self) -> &[D::Value] {
&*self.values
}
}
impl<D: SnapshotVecDelegate> ops::DerefMut for SnapshotVec<D> {
fn deref_mut(&mut self) -> &mut [D::Value] {
&mut *self.values
}
}
impl<D: SnapshotVecDelegate> ops::Index<usize> for SnapshotVec<D> {
type Output = D::Value;
fn index(&self, index: usize) -> &D::Value {
self.get(index)
}
}
impl<D: SnapshotVecDelegate> ops::IndexMut<usize> for SnapshotVec<D> {
fn index_mut(&mut self, index: usize) -> &mut D::Value {
self.get_mut(index)
}
}
impl<D: SnapshotVecDelegate> Extend<D::Value> for SnapshotVec<D> {
fn extend<T>(&mut self, iterable: T) where T: IntoIterator<Item=D::Value> {
for item in iterable {
self.push(item);
}
}
}
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::marker;
use std::fmt::Debug;
use std::marker::PhantomData;
use snapshot_vec as sv;
#[cfg(test)]
mod tests;
/// This trait is implemented by any type that can serve as a type
/// variable. We call such variables *unification keys*. For example,
/// this trait is implemented by `IntVid`, which represents integral
/// variables.
///
/// Each key type has an associated value type `V`. For example, for
/// `IntVid`, this is `Option<IntVarValue>`, representing some
/// (possibly not yet known) sort of integer.
///
/// Clients are expected to provide implementations of this trait; you
/// can see some examples in the `test` module.
pub trait UnifyKey: Copy + Clone + Debug + PartialEq {
type Value: Clone + PartialEq + Debug;
fn index(&self) -> u32;
fn from_index(u: u32) -> Self;
fn tag(k: Option<Self>) -> &'static str;
}
/// This trait is implemented for unify values that can be
/// combined. This relation should be a monoid.
pub trait Combine {
fn combine(&self, other: &Self) -> Self;
}
impl Combine for () {
fn combine(&self, _other: &()) {}
}
/// Value of a unification key. We implement Tarjan's union-find
/// algorithm: when two keys are unified, one of them is converted
/// into a "redirect" pointing at the other. These redirects form a
/// DAG: the roots of the DAG (nodes that are not redirected) are each
/// associated with a value of type `V` and a rank. The rank is used
/// to keep the DAG relatively balanced, which helps keep the running
/// time of the algorithm under control. For more information, see
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
#[derive(PartialEq,Clone,Debug)]
pub struct VarValue<K: UnifyKey> {
parent: K, // if equal to self, this is a root
value: K::Value, // value assigned (only relevant to root)
rank: u32, // max depth (only relevant to root)
}
/// Table of unification keys and their values.
pub struct UnificationTable<K: UnifyKey> {
/// Indicates the current value of each key.
values: sv::SnapshotVec<Delegate<K>>,
}
/// At any time, users may snapshot a unification table. The changes
/// made during the snapshot may either be *committed* or *rolled back*.
pub struct Snapshot<K: UnifyKey> {
// Link snapshot to the key type `K` of the table.
marker: marker::PhantomData<K>,
snapshot: sv::Snapshot,
}
#[derive(Copy, Clone)]
struct Delegate<K>(PhantomData<K>);
impl<K: UnifyKey> VarValue<K> {
fn new_var(key: K, value: K::Value) -> VarValue<K> {
VarValue::new(key, value, 0)
}
fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> {
VarValue {
parent: parent, // this is a root
value,
rank,
}
}
fn redirect(self, to: K) -> VarValue<K> {
VarValue { parent: to, ..self }
}
fn root(self, rank: u32, value: K::Value) -> VarValue<K> {
VarValue {
rank,
value,
..self
}
}
/// Returns the key of this node. Only valid if this is a root
/// node, which you yourself must ensure.
fn key(&self) -> K {
self.parent
}
fn parent(&self, self_key: K) -> Option<K> {
self.if_not_self(self.parent, self_key)
}
fn if_not_self(&self, key: K, self_key: K) -> Option<K> {
if key == self_key { None } else { Some(key) }
}
}
/// We can't use V:LatticeValue, much as I would like to,
/// because frequently the pattern is that V=Option<U> for some
/// other type parameter U, and we have no way to say
/// Option<U>:LatticeValue.
impl<K: UnifyKey> UnificationTable<K> {
pub fn new() -> UnificationTable<K> {
UnificationTable { values: sv::SnapshotVec::new() }
}
/// Starts a new snapshot. Each snapshot must be either
/// rolled back or committed in a "LIFO" (stack) order.
pub fn snapshot(&mut self) -> Snapshot<K> {
Snapshot {
marker: marker::PhantomData::<K>,
snapshot: self.values.start_snapshot(),
}
}
/// Reverses all changes since the last snapshot. Also
/// removes any keys that have been created since then.
pub fn rollback_to(&mut self, snapshot: Snapshot<K>) {
debug!("{}: rollback_to()", UnifyKey::tag(None::<K>));
self.values.rollback_to(snapshot.snapshot);
}
/// Commits all changes since the last snapshot. Of course, they
/// can still be undone if there is a snapshot further out.
pub fn commit(&mut self, snapshot: Snapshot<K>) {
debug!("{}: commit()", UnifyKey::tag(None::<K>));
self.values.commit(snapshot.snapshot);
}
pub fn new_key(&mut self, value: K::Value) -> K {
let len = self.values.len();
let key: K = UnifyKey::from_index(len as u32);
self.values.push(VarValue::new_var(key, value));
debug!("{}: created new key: {:?}", UnifyKey::tag(None::<K>), key);
key
}
/// Find the root node for `vid`. This uses the standard
/// union-find algorithm with path compression:
/// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
///
/// NB. This is a building-block operation and you would probably
/// prefer to call `probe` below.
fn get(&mut self, vid: K) -> VarValue<K> {
let index = vid.index() as usize;
let mut value: VarValue<K> = self.values.get(index).clone();
match value.parent(vid) {
Some(redirect) => {
let root: VarValue<K> = self.get(redirect);
if root.key() != redirect {
// Path compression
value.parent = root.key();
self.values.set(index, value);
}
root
}
None => value,
}
}
fn is_root(&self, key: K) -> bool {
let index = key.index() as usize;
self.values.get(index).parent(key).is_none()
}
/// Sets the value for `vid` to `new_value`. `vid` MUST be a root
/// node! This is an internal operation used to impl other things.
fn set(&mut self, key: K, new_value: VarValue<K>) {
assert!(self.is_root(key));
debug!("Updating variable {:?} to {:?}", key, new_value);
let index = key.index() as usize;
self.values.set(index, new_value);
}
/// Either redirects `node_a` to `node_b` or vice versa, depending
/// on the relative rank. The value associated with the new root
/// will be `new_value`.
///
/// NB: This is the "union" operation of "union-find". It is
/// really more of a building block. If the values associated with
/// your key are non-trivial, you would probably prefer to call
/// `unify_var_var` below.
fn unify(&mut self, root_a: VarValue<K>, root_b: VarValue<K>, new_value: K::Value) -> K {
debug!("unify(root_a(id={:?}, rank={:?}), root_b(id={:?}, rank={:?}))",
root_a.key(),
root_a.rank,
root_b.key(),
root_b.rank);
if root_a.rank > root_b.rank {
// a has greater rank, so a should become b's parent,
// i.e., b should redirect to a.
self.redirect_root(root_a.rank, root_b, root_a, new_value)
} else if root_a.rank < root_b.rank {
// b has greater rank, so a should redirect to b.
self.redirect_root(root_b.rank, root_a, root_b, new_value)
} else {
// If equal, redirect one to the other and increment the
// other's rank.
self.redirect_root(root_a.rank + 1, root_a, root_b, new_value)
}
}
fn redirect_root(&mut self,
new_rank: u32,
old_root: VarValue<K>,
new_root: VarValue<K>,
new_value: K::Value)
-> K {
let old_root_key = old_root.key();
let new_root_key = new_root.key();
self.set(old_root_key, old_root.redirect(new_root_key));
self.set(new_root_key, new_root.root(new_rank, new_value));
new_root_key
}
}
impl<K: UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
type Value = VarValue<K>;
type Undo = ();
fn reverse(_: &mut Vec<VarValue<K>>, _: ()) {}
}
/// # Base union-find algorithm, where we are just making sets
impl<'tcx, K: UnifyKey> UnificationTable<K>
where K::Value: Combine
{
pub fn union(&mut self, a_id: K, b_id: K) -> K {
let node_a = self.get(a_id);
let node_b = self.get(b_id);
let a_id = node_a.key();
let b_id = node_b.key();
if a_id != b_id {
let new_value = node_a.value.combine(&node_b.value);
self.unify(node_a, node_b, new_value)
} else {
a_id
}
}
pub fn find(&mut self, id: K) -> K {
self.get(id).key()
}
pub fn find_value(&mut self, id: K) -> K::Value {
self.get(id).value
}
#[cfg(test)]
fn unioned(&mut self, a_id: K, b_id: K) -> bool {
self.find(a_id) == self.find(b_id)
}
}
/// # Non-subtyping unification
///
/// Code to handle keys which carry a value, like ints,
/// floats---anything that doesn't have a subtyping relationship we
/// need to worry about.
impl<'tcx, K, V> UnificationTable<K>
where K: UnifyKey<Value = Option<V>>,
V: Clone + PartialEq + Debug
{
pub fn unify_var_var(&mut self, a_id: K, b_id: K) -> Result<K, (V, V)> {
let node_a = self.get(a_id);
let node_b = self.get(b_id);
let a_id = node_a.key();
let b_id = node_b.key();
if a_id == b_id {
return Ok(a_id);
}
let combined = {
match (&node_a.value, &node_b.value) {
(&None, &None) => None,
(&Some(ref v), &None) |
(&None, &Some(ref v)) => Some(v.clone()),
(&Some(ref v1), &Some(ref v2)) => {
if *v1 != *v2 {
return Err((v1.clone(), v2.clone()));
}
Some(v1.clone())
}
}
};
Ok(self.unify(node_a, node_b, combined))
}
/// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping
/// relationships, if `a_id` already has a value, it must be the same as `b`.
pub fn unify_var_value(&mut self, a_id: K, b: V) -> Result<(), (V, V)> {
let mut node_a = self.get(a_id);
match node_a.value {
None => {
node_a.value = Some(b);
self.set(node_a.key(), node_a);
Ok(())
}
Some(ref a_t) => {
if *a_t == b {
Ok(())
} else {
Err((a_t.clone(), b))
}
}
}
}
pub fn has_value(&mut self, id: K) -> bool {
self.get(id).value.is_some()
}
pub fn probe(&mut self, a_id: K) -> Option<V> {
self.get(a_id).value
}
pub fn unsolved_variables(&mut self) -> Vec<K> {
self.values
.iter()
.filter_map(|vv| {
if vv.value.is_some() {
None
} else {
Some(vv.key())
}
})
.collect()
}
}
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(non_snake_case)]
extern crate test;
use self::test::Bencher;
use unify::{UnifyKey, UnificationTable};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct UnitKey(u32);
impl UnifyKey for UnitKey {
type Value = ();
fn index(&self) -> u32 {
self.0
}
fn from_index(u: u32) -> UnitKey {
UnitKey(u)
}
fn tag(_: Option<UnitKey>) -> &'static str {
"UnitKey"
}
}
#[test]
fn basic() {
let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
let k1 = ut.new_key(());
let k2 = ut.new_key(());
assert_eq!(ut.unioned(k1, k2), false);
ut.union(k1, k2);
assert_eq!(ut.unioned(k1, k2), true);
}
#[test]
fn big_array() {
let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
let mut keys = Vec::new();
const MAX: usize = 1 << 15;
for _ in 0..MAX {
keys.push(ut.new_key(()));
}
for i in 1..MAX {
let l = keys[i - 1];
let r = keys[i];
ut.union(l, r);
}
for i in 0..MAX {
assert!(ut.unioned(keys[0], keys[i]));
}
}
#[bench]
fn big_array_bench(b: &mut Bencher) {
let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
let mut keys = Vec::new();
const MAX: usize = 1 << 15;
for _ in 0..MAX {
keys.push(ut.new_key(()));
}
b.iter(|| {
for i in 1..MAX {
let l = keys[i - 1];
let r = keys[i];
ut.union(l, r);
}
for i in 0..MAX {
assert!(ut.unioned(keys[0], keys[i]));
}
})
}
#[test]
fn even_odd() {
let mut ut: UnificationTable<UnitKey> = UnificationTable::new();
let mut keys = Vec::new();
const MAX: usize = 1 << 10;
for i in 0..MAX {
let key = ut.new_key(());
keys.push(key);
if i >= 2 {
ut.union(key, keys[i - 2]);
}
}
for i in 1..MAX {
assert!(!ut.unioned(keys[i - 1], keys[i]));
}
for i in 2..MAX {
assert!(ut.unioned(keys[i - 2], keys[i]));
}
}
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct IntKey(u32);
impl UnifyKey for IntKey {
type Value = Option<i32>;
fn index(&self) -> u32 {
self.0
}
fn from_index(u: u32) -> IntKey {
IntKey(u)
}
fn tag(_: Option<IntKey>) -> &'static str {
"IntKey"
}
}
/// Test unifying a key whose value is `Some(_)` with a key whose value is `None`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_Some_key_None() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
let k2 = ut.new_key(None);
assert!(ut.unify_var_var(k1, k2).is_ok());
assert_eq!(ut.probe(k2), Some(22));
assert_eq!(ut.probe(k1), Some(22));
}
/// Test unifying a key whose value is `None` with a key whose value is `Some(_)`.
/// Afterwards both should be `Some(_)`.
#[test]
fn unify_key_None_key_Some() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
let k2 = ut.new_key(None);
assert!(ut.unify_var_var(k2, k1).is_ok());
assert_eq!(ut.probe(k2), Some(22));
assert_eq!(ut.probe(k1), Some(22));
}
/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(y)`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_key_Some_y() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
let k2 = ut.new_key(Some(23));
assert_eq!(ut.unify_var_var(k1, k2), Err((22, 23)));
assert_eq!(ut.unify_var_var(k2, k1), Err((23, 22)));
assert_eq!(ut.probe(k1), Some(22));
assert_eq!(ut.probe(k2), Some(23));
}
/// Test unifying a key whose value is `Some(x)` with a key whose value is `Some(x)`.
/// This should be ok.
#[test]
fn unify_key_Some_x_key_Some_x() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
let k2 = ut.new_key(Some(22));
assert!(ut.unify_var_var(k1, k2).is_ok());
assert_eq!(ut.probe(k1), Some(22));
assert_eq!(ut.probe(k2), Some(22));
}
/// Test unifying a key whose value is `None` with a value is `x`.
/// Afterwards key should be `x`.
#[test]
fn unify_key_None_val() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(None);
assert!(ut.unify_var_value(k1, 22).is_ok());
assert_eq!(ut.probe(k1), Some(22));
}
/// Test unifying a key whose value is `Some(x)` with the value `y`.
/// This should yield an error.
#[test]
fn unify_key_Some_x_val_y() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
assert_eq!(ut.unify_var_value(k1, 23), Err((22, 23)));
assert_eq!(ut.probe(k1), Some(22));
}
/// Test unifying a key whose value is `Some(x)` with the value `x`.
/// This should be ok.
#[test]
fn unify_key_Some_x_val_x() {
let mut ut: UnificationTable<IntKey> = UnificationTable::new();
let k1 = ut.new_key(Some(22));
assert!(ut.unify_var_value(k1, 22).is_ok());
assert_eq!(ut.probe(k1), Some(22));
}
......@@ -444,7 +444,8 @@ fn sub_free_bound_false_infer() {
//! does NOT hold for any instantiation of `_#1`.
test_env(EMPTY_SOURCE_STR, errors(&[]), |env| {
let t_infer1 = env.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
let t_infer1 = env.infcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(DUMMY_SP));
let t_rptr_bound1 = env.t_rptr_late_bound(1);
env.check_not_sub(env.t_fn(&[t_infer1], env.tcx().types.isize),
env.t_fn(&[t_rptr_bound1], env.tcx().types.isize));
......
......@@ -51,7 +51,6 @@ fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
/// Same as ty_infer, but with a known type parameter definition.
fn ty_infer_for_def(&self,
_def: &ty::TypeParameterDef,
_substs: &[Kind<'tcx>],
span: Span) -> Ty<'tcx> {
self.ty_infer(span)
}
......@@ -261,7 +260,7 @@ fn create_substs_for_ast_path(&self,
} else if infer_types {
// No type parameters were provided, we can infer all.
let ty_var = if !default_needs_object_self(def) {
self.ty_infer_for_def(def, substs, span)
self.ty_infer_for_def(def, span)
} else {
self.ty_infer(span)
};
......
......@@ -329,6 +329,7 @@ pub fn check_pat_walk(
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));
......@@ -339,7 +340,8 @@ pub fn check_pat_walk(
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) {
......@@ -372,6 +374,7 @@ pub fn check_pat_walk(
}
_ => {
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));
......@@ -630,7 +633,8 @@ pub fn check_match(&self,
// ...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);
};
......@@ -691,7 +695,8 @@ pub fn check_match(&self,
// 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)
};
......
......@@ -110,7 +110,8 @@ fn check_closure(
|_, _| 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 };
......
......@@ -177,6 +177,7 @@ fn coerce(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'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 {
......@@ -510,7 +511,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
// 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,
......
......@@ -218,7 +218,8 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// the new hybrid bounds we computed.
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
let param_env = ty::ParamEnv::new(tcx.intern_predicates(&hybrid_preds.predicates),
Reveal::UserFacing);
Reveal::UserFacing,
ty::UniverseIndex::ROOT);
let param_env = traits::normalize_param_env_or_error(tcx,
impl_m.def_id,
param_env,
......
......@@ -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);
......
......@@ -259,7 +259,7 @@ fn fresh_receiver_substs(&mut self,
// 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) => {
......@@ -325,7 +325,7 @@ fn instantiate_method_substs(&mut self,
} else {
self.region_var_for_def(self.span, def)
}
}, |def, cur_substs| {
}, |def, _cur_substs| {
let i = def.index as usize;
if i < parent_substs.len() {
parent_substs.type_at(i)
......@@ -336,7 +336,7 @@ fn instantiate_method_substs(&mut self,
{
self.to_ty(ast_ty)
} else {
self.type_var_for_def(self.span, def, cur_substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def)
}
})
}
......
......@@ -249,13 +249,13 @@ pub fn lookup_method_in_trait(&self,
let substs = Substs::for_item(self.tcx,
trait_def_id,
|def, _| self.region_var_for_def(span, def),
|def, substs| {
|def, _substs| {
if def.index == 0 {
self_ty
} 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, substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, span, def)
}
});
......
......@@ -730,7 +730,9 @@ pub fn matches_return_type(&self,
Def::Method(def_id) => {
let fty = self.tcx.fn_sig(def_id);
self.probe(|_| {
let substs = self.fresh_substs_for_item(self.span, method.def_id);
let substs = self.fresh_substs_for_item(ty::UniverseIndex::ROOT,
self.span,
method.def_id);
let fty = fty.subst(self.tcx, substs);
let (fty, _) = self.replace_late_bound_regions_with_fresh_var(
self.span, infer::FnCall, &fty);
......@@ -1304,12 +1306,12 @@ fn xform_method_sig(&self,
// `impl_self_ty()` for an explanation.
self.tcx.types.re_erased
}
}, |def, cur_substs| {
}, |def, _cur_substs| {
let i = def.index as usize;
if i < substs.len() {
substs.type_at(i)
} else {
self.type_var_for_def(self.span, def, cur_substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, self.span, def)
}
});
xform_fn_sig.subst(self.tcx, substs)
......@@ -1326,6 +1328,7 @@ fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
def_id,
|_, _| self.tcx.types.re_erased,
|_, _| self.next_ty_var(
ty::UniverseIndex::ROOT,
TypeVariableOrigin::SubstitutionPlaceholder(
self.tcx.def_span(def_id))))
}
......
......@@ -54,7 +54,8 @@ fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool {
self.autoderef(span, ty).any(|(ty, _)| {
self.probe(|_| {
let fn_once_substs = tcx.mk_substs_trait(ty,
&[self.next_ty_var(TypeVariableOrigin::MiscVariable(span))]);
&[self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(span))]);
let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
let poly_trait_ref = trait_ref.to_poly_trait_ref();
let obligation =
......
......@@ -362,7 +362,8 @@ fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
/// hard constraint exists, creates a fresh type variable.
fn coercion_target_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, span: Span) -> Ty<'tcx> {
self.only_has_type(fcx)
.unwrap_or_else(|| fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span)))
.unwrap_or_else(|| fcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(span)))
}
}
......@@ -921,7 +922,8 @@ fn assign(&mut self, span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) ->
match ty_opt {
None => {
// infer the variable's type
let var_ty = self.fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
let var_ty = self.fcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(span));
self.fcx.locals.borrow_mut().insert(nid, var_ty);
var_ty
}
......@@ -1025,7 +1027,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
let span = body.value.span;
if body.is_generator && can_be_generator.is_some() {
let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
let yield_ty = fcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(span));
fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
fcx.yield_ty = Some(yield_ty);
}
......@@ -1058,7 +1061,8 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
// This ensures that all nested generators appear before the entry of this generator.
// resolve_generator_interiors relies on this property.
let gen_ty = if can_be_generator.is_some() && body.is_generator {
let witness = fcx.next_ty_var(TypeVariableOrigin::MiscVariable(span));
let witness = fcx.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(span));
let interior = ty::GeneratorInterior {
witness,
movable: can_be_generator.unwrap() == hir::GeneratorMovability::Movable,
......@@ -1096,6 +1100,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
let mut actual_return_ty = coercion.complete(&fcx);
if actual_return_ty.is_never() {
actual_return_ty = fcx.next_diverging_ty_var(
ty::UniverseIndex::ROOT,
TypeVariableOrigin::DivergingFn(span));
}
fcx.demand_suptype(span, ret_ty, actual_return_ty);
......@@ -1687,14 +1692,14 @@ fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
}
fn ty_infer(&self, span: Span) -> Ty<'tcx> {
self.next_ty_var(TypeVariableOrigin::TypeInference(span))
self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(span))
}
fn ty_infer_for_def(&self,
ty_param_def: &ty::TypeParameterDef,
substs: &[Kind<'tcx>],
span: Span) -> Ty<'tcx> {
self.type_var_for_def(span, ty_param_def, substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, span, ty_param_def)
}
fn projected_ty_from_poly_trait_ref(&self,
......@@ -2316,7 +2321,8 @@ fn try_index_step(&self,
// If some lookup succeeds, write callee into table and extract index/element
// type from the method signature.
// If some lookup succeeded, install method in table
let input_ty = self.next_ty_var(TypeVariableOrigin::AutoDeref(base_expr.span));
let input_ty = self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::AutoDeref(base_expr.span));
let method = self.try_overloaded_place_op(
expr.span, self_ty, &[input_ty], needs, PlaceOp::Index);
......@@ -2755,6 +2761,7 @@ fn check_expr_meets_expectation_or_error(&self,
assert!(!self.tables.borrow().adjustments().contains_key(expr.hir_id),
"expression with never type wound up being adjusted");
let adj_ty = self.next_diverging_ty_var(
ty::UniverseIndex::ROOT,
TypeVariableOrigin::AdjustmentType(expr.span));
self.apply_adjustments(expr, vec![Adjustment {
kind: Adjust::NeverToAny,
......@@ -2832,7 +2839,7 @@ pub fn impl_self_ty(&self,
let ity = self.tcx.type_of(did);
debug!("impl_self_ty: ity={:?}", ity);
let substs = self.fresh_substs_for_item(span, did);
let substs = self.fresh_substs_for_item(ty::UniverseIndex::ROOT, span, did);
let substd_ty = self.instantiate_type_scheme(span, &substs, &ity);
TypeAndSubsts { substs: substs, ty: substd_ty }
......@@ -3972,7 +3979,8 @@ fn check_expr_kind(&self,
let element_ty = if !args.is_empty() {
let coerce_to = uty.unwrap_or_else(
|| self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span)));
|| self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(expr.span)));
let mut coerce = CoerceMany::with_coercion_sites(coerce_to, args);
assert_eq!(self.diverges.get(), Diverges::Maybe);
for e in args {
......@@ -3982,7 +3990,8 @@ fn check_expr_kind(&self,
}
coerce.complete(self)
} else {
self.next_ty_var(TypeVariableOrigin::TypeInference(expr.span))
self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::TypeInference(expr.span))
};
tcx.mk_array(element_ty, args.len() as u64)
}
......@@ -4012,7 +4021,8 @@ fn check_expr_kind(&self,
(uty, uty)
}
None => {
let t: Ty = self.next_ty_var(TypeVariableOrigin::MiscVariable(element.span));
let t: Ty = self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(element.span));
let element_ty = self.check_expr_has_type_or_error(&element, t);
(element_ty, t)
}
......@@ -4793,7 +4803,7 @@ pub fn instantiate_value_path(&self,
// Handle Self first, so we can adjust the index to match the AST.
if has_self && i == 0 {
return opt_self_ty.unwrap_or_else(|| {
self.type_var_for_def(span, def, substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, span, def)
});
}
i -= has_self as usize;
......@@ -4826,7 +4836,7 @@ pub fn instantiate_value_path(&self,
// This can also be reached in some error cases:
// We prefer to use inference variables instead of
// TyError to let type inference recover somewhat.
self.type_var_for_def(span, def, substs)
self.type_var_for_def(ty::UniverseIndex::ROOT, span, def)
}
});
......
......@@ -174,8 +174,10 @@ fn check_overloaded_binop(&self,
// trait matching creating lifetime constraints that are too strict.
// E.g. adding `&'a T` and `&'b T`, given `&'x T: Add<&'x T>`, will result
// in `&'a T <: &'x T` and `&'b T <: &'x T`, instead of `'a = 'b = 'x`.
let lhs_ty = self.check_expr_coercable_to_type_with_needs(lhs_expr,
self.next_ty_var(TypeVariableOrigin::MiscVariable(lhs_expr.span)),
let lhs_ty = self.check_expr_coercable_to_type_with_needs(
lhs_expr,
self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(lhs_expr.span)),
lhs_needs);
let lhs_ty = self.resolve_type_vars_with_obligations(lhs_ty);
......@@ -185,7 +187,8 @@ fn check_overloaded_binop(&self,
// using this variable as the expected type, which sometimes lets
// us do better coercions than we would be able to do otherwise,
// particularly for things like `String + &String`.
let rhs_ty_var = self.next_ty_var(TypeVariableOrigin::MiscVariable(rhs_expr.span));
let rhs_ty_var = self.next_ty_var(ty::UniverseIndex::ROOT,
TypeVariableOrigin::MiscVariable(rhs_expr.span));
let result = self.lookup_op_method(lhs_ty, &[rhs_ty_var], Op::Binary(op, is_assign));
......
......@@ -681,12 +681,17 @@ fn evaluate_predicates<'b, 'gcx, 'c>(
computed_preds.extend(user_computed_preds.iter().cloned());
let normalized_preds =
traits::elaborate_predicates(tcx, computed_preds.clone().into_iter().collect());
new_env = ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal);
new_env = ty::ParamEnv::new(
tcx.mk_predicates(normalized_preds),
param_env.reveal,
ty::UniverseIndex::ROOT,
);
}
let final_user_env = ty::ParamEnv::new(
tcx.mk_predicates(user_computed_preds.into_iter()),
user_env.reveal,
ty::UniverseIndex::ROOT,
);
debug!(
"evaluate_nested_obligations(ty_did={:?}, trait_did={:?}): succeeded with '{:?}' \
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册