1
Fork 0

Extract more ty and infer dependencies from the unification engine

so that it is closer to standalone.
This commit is contained in:
Niko Matsakis 2015-03-10 15:32:25 -04:00
parent c581840dcc
commit a6d9930525
5 changed files with 66 additions and 63 deletions

View file

@ -436,8 +436,17 @@ pub fn expected_found<'tcx, C, T>(this: &C,
a: T,
b: T)
-> ty::expected_found<T>
where C: Combine<'tcx> {
if this.a_is_expected() {
where C: Combine<'tcx>
{
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}
} else {
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))) => {
try!(this.infcx().int_unification_table
.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)
}
(&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))) => {
try!(this.infcx().float_unification_table
.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)
}
(&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>>
where C: Combine<'tcx>
{
try!(this.infcx().int_unification_table
.borrow_mut()
.unify_var_value(vid_is_expected, vid, val));
try!(this.infcx()
.int_unification_table
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| int_unification_error(vid_is_expected, e)));
match val {
IntType(v) => Ok(ty::mk_mach_int(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
.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))
}
}
@ -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))
}

View file

@ -37,6 +37,7 @@ use middle::ty_fold::TypeFolder;
use std::collections::hash_map::{self, Entry};
use super::InferCtxt;
use super::unify::ToType;
pub struct TypeFreshener<'a, 'tcx:'a> {
infcx: &'a InferCtxt<'a, 'tcx>,
@ -115,14 +116,18 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
ty::ty_infer(ty::IntVar(v)) => {
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::FreshIntTy)
}
ty::ty_infer(ty::FloatVar(v)) => {
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::FreshIntTy)
}

View file

@ -43,7 +43,7 @@ use self::region_inference::{RegionVarBindings, RegionSnapshot};
use self::equate::Equate;
use self::sub::Sub;
use self::lub::Lub;
use self::unify::UnificationTable;
use self::unify::{ToType, UnificationTable};
use self::error_reporting::ErrorReporting;
pub mod bivariate;
@ -885,14 +885,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
ty::ty_infer(ty::IntVar(v)) => {
self.int_unification_table
.borrow_mut()
.probe(self.tcx, v)
.probe(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ)
}
ty::ty_infer(ty::FloatVar(v)) => {
self.float_unification_table
.borrow_mut()
.probe(self.tcx, v)
.probe(v)
.map(|v| v.to_type(self.tcx))
.unwrap_or(typ)
}

View file

@ -14,7 +14,6 @@ use std::marker;
use middle::ty::{expected_found, IntVarValue};
use middle::ty::{self, Ty};
use middle::infer::{UnitResult};
use std::fmt::Debug;
use std::marker::PhantomData;
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
// 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>
where K : UnifyKey<Value=Option<V>>,
V : SimplyUnifiable<'tcx>,
Option<V> : UnifyValue,
where K: UnifyKey<Value=Option<V>>,
V: Clone+PartialEq,
Option<V>: UnifyValue,
{
pub fn unify_var_var(&mut self,
a_is_expected: bool,
a_id: K,
b_id: K)
-> UnitResult<'tcx>
-> Result<(),(V,V)>
{
let node_a = self.get(a_id);
let node_b = self.get(b_id);
@ -268,13 +246,13 @@ impl<'tcx,K,V> UnificationTable<K>
None
}
(&Some(ref v), &None) | (&None, &Some(ref v)) => {
Some((*v).clone())
Some(v.clone())
}
(&Some(ref v1), &Some(ref 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
/// relationships, if `a_id` already has a value, it must be the same as `b`.
pub fn unify_var_value(&mut self,
a_is_expected: bool,
a_id: K,
b: V)
-> UnitResult<'tcx>
-> Result<(),(V,V)>
{
let node_a = self.get(a_id);
let a_id = node_a.key.clone();
@ -303,7 +280,7 @@ impl<'tcx,K,V> UnificationTable<K>
if *a_t == b {
Ok(())
} 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()
}
pub fn probe(&mut self, tcx: &ty::ctxt<'tcx>, a_id: K) -> Option<Ty<'tcx>> {
let node_a = self.get(a_id);
match node_a.value {
None => None,
Some(ref a_t) => Some(a_t.to_type(tcx))
}
pub fn probe(&mut self, a_id: K) -> Option<V> {
self.get(a_id).value.clone()
}
}
@ -326,6 +299,10 @@ impl<'tcx,K,V> UnificationTable<K>
// Integral type keys
pub trait ToType<'tcx> {
fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
}
impl UnifyKey for ty::IntVid {
type Value = Option<IntVarValue>;
fn index(&self) -> u32 { self.index }
@ -333,17 +310,13 @@ impl UnifyKey for ty::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> {
match *self {
ty::IntType(i) => ty::mk_mach_int(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> { }
@ -360,12 +333,8 @@ impl UnifyKey for ty::FloatVid {
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> {
ty::mk_mach_float(tcx, *self)
}
fn to_type_err(err: expected_found<ast::FloatTy>) -> ty::type_err<'tcx> {
ty::terr_float_mismatch(err)
}
}

View file

@ -62,9 +62,8 @@
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::sub::Sub;
use middle::subst;
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
use middle::ty::{self, mt, Ty};