diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index b3f4537f472..fdff750bf46 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -436,8 +436,17 @@ pub fn expected_found<'tcx, C, T>(this: &C, a: T, b: T) -> ty::expected_found - 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(a_is_expected: bool, + a: T, + b: T) + -> ty::expected_found +{ + 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)) +} diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs index 39a0a276b28..29f74d12ea3 100644 --- a/src/librustc/middle/infer/freshen.rs +++ b/src/librustc/middle/infer/freshen.rs @@ -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) } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 15c30847031..7e9c4d8e076 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -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) } diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 5effaca32b1..a240917d6c1 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -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 sv::SnapshotVecDelegate for Delegate { // 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) -> 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 - where K : UnifyKey>, - V : SimplyUnifiable<'tcx>, - Option : UnifyValue, + where K: UnifyKey>, + V: Clone+PartialEq, + Option: 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 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 /// 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 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 self.get(id).value.is_some() } - pub fn probe(&mut self, tcx: &ty::ctxt<'tcx>, a_id: K) -> Option> { - 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 { + self.get(a_id).value.clone() } } @@ -326,6 +299,10 @@ impl<'tcx,K,V> UnificationTable // 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; fn index(&self) -> u32 { self.index } @@ -333,17 +310,13 @@ impl UnifyKey for ty::IntVid { fn tag(_: Option) -> &'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) -> ty::type_err<'tcx> { - return ty::terr_int_mismatch(err); - } } impl UnifyValue for Option { } @@ -360,12 +333,8 @@ impl UnifyKey for ty::FloatVid { impl UnifyValue for Option { } -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) -> ty::type_err<'tcx> { - ty::terr_float_mismatch(err) - } } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 0765d7294ad..1ba0194f84e 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -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};