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, 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()
.int_unification_table
.borrow_mut() .borrow_mut()
.unify_var_value(vid_is_expected, vid, val)); .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))
}

View file

@ -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)
} }

View file

@ -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)
} }

View file

@ -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)
}
} }

View file

@ -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};