Extract more ty
and infer
dependencies from the unification engine
so that it is closer to standalone.
This commit is contained in:
parent
c581840dcc
commit
a6d9930525
5 changed files with 66 additions and 63 deletions
|
@ -436,8 +436,17 @@ pub fn expected_found<'tcx, C, T>(this: &C,
|
||||||
a: T,
|
a: T,
|
||||||
b: T)
|
b: T)
|
||||||
-> ty::expected_found<T>
|
-> ty::expected_found<T>
|
||||||
where C: Combine<'tcx> {
|
where C: Combine<'tcx>
|
||||||
if this.a_is_expected() {
|
{
|
||||||
|
expected_found_bool(this.a_is_expected(), a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expected_found_bool<T>(a_is_expected: bool,
|
||||||
|
a: T,
|
||||||
|
b: T)
|
||||||
|
-> ty::expected_found<T>
|
||||||
|
{
|
||||||
|
if a_is_expected {
|
||||||
ty::expected_found {expected: a, found: b}
|
ty::expected_found {expected: a, found: b}
|
||||||
} else {
|
} else {
|
||||||
ty::expected_found {expected: b, found: a}
|
ty::expected_found {expected: b, found: a}
|
||||||
|
@ -469,7 +478,8 @@ pub fn super_tys<'tcx, C>(this: &C,
|
||||||
(&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
|
(&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
|
||||||
try!(this.infcx().int_unification_table
|
try!(this.infcx().int_unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.unify_var_var(this.a_is_expected(), a_id, b_id));
|
.unify_var_var(a_id, b_id)
|
||||||
|
.map_err(|e| int_unification_error(this.a_is_expected(), e)));
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
(&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => {
|
(&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => {
|
||||||
|
@ -489,7 +499,8 @@ pub fn super_tys<'tcx, C>(this: &C,
|
||||||
(&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => {
|
(&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => {
|
||||||
try!(this.infcx().float_unification_table
|
try!(this.infcx().float_unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.unify_var_var(this.a_is_expected(), a_id, b_id));
|
.unify_var_var(a_id, b_id)
|
||||||
|
.map_err(|e| float_unification_error(this.a_is_expected(), e)));
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
(&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => {
|
(&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => {
|
||||||
|
@ -617,9 +628,11 @@ pub fn super_tys<'tcx, C>(this: &C,
|
||||||
-> CombineResult<'tcx, Ty<'tcx>>
|
-> CombineResult<'tcx, Ty<'tcx>>
|
||||||
where C: Combine<'tcx>
|
where C: Combine<'tcx>
|
||||||
{
|
{
|
||||||
try!(this.infcx().int_unification_table
|
try!(this.infcx()
|
||||||
.borrow_mut()
|
.int_unification_table
|
||||||
.unify_var_value(vid_is_expected, vid, val));
|
.borrow_mut()
|
||||||
|
.unify_var_value(vid, val)
|
||||||
|
.map_err(|e| int_unification_error(vid_is_expected, e)));
|
||||||
match val {
|
match val {
|
||||||
IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
|
IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
|
||||||
UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
|
UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
|
||||||
|
@ -635,7 +648,8 @@ pub fn super_tys<'tcx, C>(this: &C,
|
||||||
{
|
{
|
||||||
try!(this.infcx().float_unification_table
|
try!(this.infcx().float_unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.unify_var_value(vid_is_expected, vid, val));
|
.unify_var_value(vid, val)
|
||||||
|
.map_err(|e| float_unification_error(vid_is_expected, e)));
|
||||||
Ok(ty::mk_mach_float(this.tcx(), val))
|
Ok(ty::mk_mach_float(this.tcx(), val))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -863,3 +877,17 @@ impl<'tcx, T:Clone + PartialEq> CombineResultCompare<'tcx, T> for CombineResult<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue))
|
||||||
|
-> ty::type_err<'tcx>
|
||||||
|
{
|
||||||
|
let (a, b) = v;
|
||||||
|
ty::terr_int_mismatch(expected_found_bool(a_is_expected, a, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn float_unification_error<'tcx>(a_is_expected: bool,
|
||||||
|
v: (ast::FloatTy, ast::FloatTy))
|
||||||
|
-> ty::type_err<'tcx>
|
||||||
|
{
|
||||||
|
let (a, b) = v;
|
||||||
|
ty::terr_float_mismatch(expected_found_bool(a_is_expected, a, b))
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ use middle::ty_fold::TypeFolder;
|
||||||
use std::collections::hash_map::{self, Entry};
|
use std::collections::hash_map::{self, Entry};
|
||||||
|
|
||||||
use super::InferCtxt;
|
use super::InferCtxt;
|
||||||
|
use super::unify::ToType;
|
||||||
|
|
||||||
pub struct TypeFreshener<'a, 'tcx:'a> {
|
pub struct TypeFreshener<'a, 'tcx:'a> {
|
||||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
|
@ -115,14 +116,18 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
||||||
|
|
||||||
ty::ty_infer(ty::IntVar(v)) => {
|
ty::ty_infer(ty::IntVar(v)) => {
|
||||||
self.freshen(
|
self.freshen(
|
||||||
self.infcx.int_unification_table.borrow_mut().probe(tcx, v),
|
self.infcx.int_unification_table.borrow_mut()
|
||||||
|
.probe(v)
|
||||||
|
.map(|v| v.to_type(tcx)),
|
||||||
ty::IntVar(v),
|
ty::IntVar(v),
|
||||||
ty::FreshIntTy)
|
ty::FreshIntTy)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_infer(ty::FloatVar(v)) => {
|
ty::ty_infer(ty::FloatVar(v)) => {
|
||||||
self.freshen(
|
self.freshen(
|
||||||
self.infcx.float_unification_table.borrow_mut().probe(tcx, v),
|
self.infcx.float_unification_table.borrow_mut()
|
||||||
|
.probe(v)
|
||||||
|
.map(|v| v.to_type(tcx)),
|
||||||
ty::FloatVar(v),
|
ty::FloatVar(v),
|
||||||
ty::FreshIntTy)
|
ty::FreshIntTy)
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ use self::region_inference::{RegionVarBindings, RegionSnapshot};
|
||||||
use self::equate::Equate;
|
use self::equate::Equate;
|
||||||
use self::sub::Sub;
|
use self::sub::Sub;
|
||||||
use self::lub::Lub;
|
use self::lub::Lub;
|
||||||
use self::unify::UnificationTable;
|
use self::unify::{ToType, UnificationTable};
|
||||||
use self::error_reporting::ErrorReporting;
|
use self::error_reporting::ErrorReporting;
|
||||||
|
|
||||||
pub mod bivariate;
|
pub mod bivariate;
|
||||||
|
@ -885,14 +885,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||||
ty::ty_infer(ty::IntVar(v)) => {
|
ty::ty_infer(ty::IntVar(v)) => {
|
||||||
self.int_unification_table
|
self.int_unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.probe(self.tcx, v)
|
.probe(v)
|
||||||
|
.map(|v| v.to_type(self.tcx))
|
||||||
.unwrap_or(typ)
|
.unwrap_or(typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ty_infer(ty::FloatVar(v)) => {
|
ty::ty_infer(ty::FloatVar(v)) => {
|
||||||
self.float_unification_table
|
self.float_unification_table
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.probe(self.tcx, v)
|
.probe(v)
|
||||||
|
.map(|v| v.to_type(self.tcx))
|
||||||
.unwrap_or(typ)
|
.unwrap_or(typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ use std::marker;
|
||||||
|
|
||||||
use middle::ty::{expected_found, IntVarValue};
|
use middle::ty::{expected_found, IntVarValue};
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use middle::infer::{UnitResult};
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
@ -224,36 +223,15 @@ impl<K:UnifyKey> sv::SnapshotVecDelegate for Delegate<K> {
|
||||||
// floats---anything that doesn't have a subtyping relationship we
|
// floats---anything that doesn't have a subtyping relationship we
|
||||||
// need to worry about.
|
// need to worry about.
|
||||||
|
|
||||||
/// Indicates a type that does not have any kind of subtyping
|
|
||||||
/// relationship.
|
|
||||||
pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Debug {
|
|
||||||
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
|
|
||||||
fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn err<'tcx, V:SimplyUnifiable<'tcx>>(a_is_expected: bool,
|
|
||||||
a_t: V,
|
|
||||||
b_t: V)
|
|
||||||
-> UnitResult<'tcx> {
|
|
||||||
if a_is_expected {
|
|
||||||
Err(SimplyUnifiable::to_type_err(
|
|
||||||
ty::expected_found {expected: a_t, found: b_t}))
|
|
||||||
} else {
|
|
||||||
Err(SimplyUnifiable::to_type_err(
|
|
||||||
ty::expected_found {expected: b_t, found: a_t}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx,K,V> UnificationTable<K>
|
impl<'tcx,K,V> UnificationTable<K>
|
||||||
where K : UnifyKey<Value=Option<V>>,
|
where K: UnifyKey<Value=Option<V>>,
|
||||||
V : SimplyUnifiable<'tcx>,
|
V: Clone+PartialEq,
|
||||||
Option<V> : UnifyValue,
|
Option<V>: UnifyValue,
|
||||||
{
|
{
|
||||||
pub fn unify_var_var(&mut self,
|
pub fn unify_var_var(&mut self,
|
||||||
a_is_expected: bool,
|
|
||||||
a_id: K,
|
a_id: K,
|
||||||
b_id: K)
|
b_id: K)
|
||||||
-> UnitResult<'tcx>
|
-> Result<(),(V,V)>
|
||||||
{
|
{
|
||||||
let node_a = self.get(a_id);
|
let node_a = self.get(a_id);
|
||||||
let node_b = self.get(b_id);
|
let node_b = self.get(b_id);
|
||||||
|
@ -268,13 +246,13 @@ impl<'tcx,K,V> UnificationTable<K>
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
(&Some(ref v), &None) | (&None, &Some(ref v)) => {
|
(&Some(ref v), &None) | (&None, &Some(ref v)) => {
|
||||||
Some((*v).clone())
|
Some(v.clone())
|
||||||
}
|
}
|
||||||
(&Some(ref v1), &Some(ref v2)) => {
|
(&Some(ref v1), &Some(ref v2)) => {
|
||||||
if *v1 != *v2 {
|
if *v1 != *v2 {
|
||||||
return err(a_is_expected, (*v1).clone(), (*v2).clone())
|
return Err((v1.clone(), v2.clone()));
|
||||||
}
|
}
|
||||||
Some((*v1).clone())
|
Some(v1.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -285,10 +263,9 @@ impl<'tcx,K,V> UnificationTable<K>
|
||||||
/// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping
|
/// 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`.
|
/// relationships, if `a_id` already has a value, it must be the same as `b`.
|
||||||
pub fn unify_var_value(&mut self,
|
pub fn unify_var_value(&mut self,
|
||||||
a_is_expected: bool,
|
|
||||||
a_id: K,
|
a_id: K,
|
||||||
b: V)
|
b: V)
|
||||||
-> UnitResult<'tcx>
|
-> Result<(),(V,V)>
|
||||||
{
|
{
|
||||||
let node_a = self.get(a_id);
|
let node_a = self.get(a_id);
|
||||||
let a_id = node_a.key.clone();
|
let a_id = node_a.key.clone();
|
||||||
|
@ -303,7 +280,7 @@ impl<'tcx,K,V> UnificationTable<K>
|
||||||
if *a_t == b {
|
if *a_t == b {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
err(a_is_expected, (*a_t).clone(), b)
|
Err((a_t.clone(), b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,12 +290,8 @@ impl<'tcx,K,V> UnificationTable<K>
|
||||||
self.get(id).value.is_some()
|
self.get(id).value.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn probe(&mut self, tcx: &ty::ctxt<'tcx>, a_id: K) -> Option<Ty<'tcx>> {
|
pub fn probe(&mut self, a_id: K) -> Option<V> {
|
||||||
let node_a = self.get(a_id);
|
self.get(a_id).value.clone()
|
||||||
match node_a.value {
|
|
||||||
None => None,
|
|
||||||
Some(ref a_t) => Some(a_t.to_type(tcx))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +299,10 @@ impl<'tcx,K,V> UnificationTable<K>
|
||||||
|
|
||||||
// Integral type keys
|
// Integral type keys
|
||||||
|
|
||||||
|
pub trait ToType<'tcx> {
|
||||||
|
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
|
||||||
|
}
|
||||||
|
|
||||||
impl UnifyKey for ty::IntVid {
|
impl UnifyKey for ty::IntVid {
|
||||||
type Value = Option<IntVarValue>;
|
type Value = Option<IntVarValue>;
|
||||||
fn index(&self) -> u32 { self.index }
|
fn index(&self) -> u32 { self.index }
|
||||||
|
@ -333,17 +310,13 @@ impl UnifyKey for ty::IntVid {
|
||||||
fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
|
fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue {
|
impl<'tcx> ToType<'tcx> for IntVarValue {
|
||||||
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
|
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
ty::IntType(i) => ty::mk_mach_int(tcx, i),
|
ty::IntType(i) => ty::mk_mach_int(tcx, i),
|
||||||
ty::UintType(i) => ty::mk_mach_uint(tcx, i),
|
ty::UintType(i) => ty::mk_mach_uint(tcx, i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_type_err(err: expected_found<IntVarValue>) -> ty::type_err<'tcx> {
|
|
||||||
return ty::terr_int_mismatch(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnifyValue for Option<IntVarValue> { }
|
impl UnifyValue for Option<IntVarValue> { }
|
||||||
|
@ -360,12 +333,8 @@ impl UnifyKey for ty::FloatVid {
|
||||||
impl UnifyValue for Option<ast::FloatTy> {
|
impl UnifyValue for Option<ast::FloatTy> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
|
impl<'tcx> ToType<'tcx> for ast::FloatTy {
|
||||||
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
|
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
|
||||||
ty::mk_mach_float(tcx, *self)
|
ty::mk_mach_float(tcx, *self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_type_err(err: expected_found<ast::FloatTy>) -> ty::type_err<'tcx> {
|
|
||||||
ty::terr_float_mismatch(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,8 @@
|
||||||
|
|
||||||
use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction};
|
use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction};
|
||||||
|
|
||||||
use middle::infer::{self, CombineResult, Coercion, TypeTrace};
|
use middle::infer::{self, CombineResult, Coercion};
|
||||||
use middle::infer::combine::Combine;
|
use middle::infer::combine::Combine;
|
||||||
use middle::infer::sub::Sub;
|
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
|
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
|
||||||
use middle::ty::{self, mt, Ty};
|
use middle::ty::{self, mt, Ty};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue