diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index d1cc7d7bc401b..462df5a48a332 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -684,7 +684,7 @@ impl<'a> AstConv for Context<'a>{ } fn ty_infer(&self, _span: Span) -> ty::t { - infer::new_infer_ctxt(self.tcx).next_ty_var() + infer::new_infer_ctxt(self.tcx).next_ty_var(None) } } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 9ceb313250901..d04690a02ea77 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -32,7 +32,7 @@ pub fn check_match(fcx: &FnCtxt, arms: &[ast::Arm]) { let tcx = fcx.ccx.tcx; - let discrim_ty = fcx.infcx().next_ty_var(); + let discrim_ty = fcx.infcx().next_ty_var(None); check_expr_has_type(fcx, discrim, discrim_ty); // Typecheck the patterns first, so that we get types for all the diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 3b33a17d5825f..24b866153b381 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -1095,24 +1095,22 @@ impl<'a> LookupContext<'a> { // If they were not explicitly supplied, just construct fresh // variables. let num_supplied_tps = self.supplied_tps.len(); - let num_method_tps = candidate.method_ty.generics.type_param_defs().len(); - let m_substs = { - if num_supplied_tps == 0u { - self.fcx.infcx().next_ty_vars(num_method_tps) - } else if num_method_tps == 0u { - tcx.sess.span_err( - self.span, - "this method does not take type parameters"); - self.fcx.infcx().next_ty_vars(num_method_tps) - } else if num_supplied_tps != num_method_tps { - tcx.sess.span_err( - self.span, - "incorrect number of type \ - parameters given for this method"); - self.fcx.infcx().next_ty_vars(num_method_tps) - } else { - Vec::from_slice(self.supplied_tps) - } + let method_tps = candidate.method_ty.generics.type_param_defs(); + let m_substs = if num_supplied_tps == 0u { + self.fcx.infcx().next_ty_vars(method_tps) + } else if method_tps.len() == 0u { + tcx.sess.span_err( + self.span, + "this method does not take type parameters"); + self.fcx.infcx().next_ty_vars(method_tps) + } else if num_supplied_tps != method_tps.len() { + tcx.sess.span_err( + self.span, + "incorrect number of type \ + parameters given for this method"); + self.fcx.infcx().next_ty_vars(method_tps) + } else { + Vec::from_slice(self.supplied_tps) }; // Determine values for the early-bound lifetime parameters. diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5e05be1ac9152..a21b26f26b881 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -367,18 +367,17 @@ struct GatherLocalsVisitor<'a> { impl<'a> GatherLocalsVisitor<'a> { fn assign(&mut self, nid: ast::NodeId, ty_opt: Option) { - match ty_opt { - None => { - // infer the variable's type - let var_id = self.fcx.infcx().next_ty_var_id(); - let var_ty = ty::mk_var(self.fcx.tcx(), var_id); - self.fcx.inh.locals.borrow_mut().insert(nid, var_ty); - } - Some(typ) => { - // take type that the user specified - self.fcx.inh.locals.borrow_mut().insert(nid, typ); - } + match ty_opt { + None => { + // infer the variable's type + let var_ty = self.fcx.infcx().next_ty_var(None); + self.fcx.inh.locals.borrow_mut().insert(nid, var_ty); + } + Some(typ) => { + // take type that the user specified + self.fcx.inh.locals.borrow_mut().insert(nid, typ); } + } } } @@ -1051,7 +1050,7 @@ impl<'a> AstConv for FnCtxt<'a> { } fn ty_infer(&self, _span: Span) -> ty::t { - self.infcx().next_ty_var() + self.infcx().next_ty_var(None) } } @@ -1479,20 +1478,16 @@ pub fn impl_self_ty(vcx: &VtableContext, let tcx = vcx.tcx(); let ity = ty::lookup_item_type(tcx, did); - let (n_tps, rps, raw_ty) = - (ity.generics.type_param_defs().len(), - ity.generics.region_param_defs(), - ity.ty); + let rps = ity.generics.region_param_defs(); let rps = vcx.infcx.region_vars_for_defs(span, rps); - let tps = vcx.infcx.next_ty_vars(n_tps); let substs = substs { regions: ty::NonerasedRegions(rps), self_ty: None, - tps: tps, + tps: vcx.infcx.next_ty_vars(ity.generics.type_param_defs()), }; - let substd_ty = ty::subst(tcx, &substs, raw_ty); + let substd_ty = ty::subst(tcx, &substs, ity.ty); ty_param_substs_and_ty { substs: substs, ty: substd_ty } } @@ -2097,7 +2092,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } if ty::is_binopable(tcx, lhs_t, op) { - let tvar = fcx.infcx().next_ty_var(); + let tvar = fcx.infcx().next_ty_var(None); demand::suptype(fcx, expr.span, tvar, lhs_t); check_expr_has_type(fcx, rhs, tvar); @@ -2477,17 +2472,15 @@ fn check_expr_with_unifier(fcx: &FnCtxt, // Look up the number of type parameters and the raw type, and // determine whether the class is region-parameterized. let item_type = ty::lookup_item_type(tcx, class_id); - let type_parameter_count = item_type.generics.type_param_defs().len(); let region_param_defs = item_type.generics.region_param_defs(); let raw_type = item_type.ty; // Generate the struct type. let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs); - let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count); let substitutions = substs { regions: ty::NonerasedRegions(regions), self_ty: None, - tps: type_parameters + tps: fcx.infcx().next_ty_vars(item_type.generics.type_param_defs()) }; let mut struct_type = ty::subst(tcx, &substitutions, raw_type); @@ -2533,17 +2526,15 @@ fn check_expr_with_unifier(fcx: &FnCtxt, // Look up the number of type parameters and the raw type, and // determine whether the enum is region-parameterized. let item_type = ty::lookup_item_type(tcx, enum_id); - let type_parameter_count = item_type.generics.type_param_defs().len(); let region_param_defs = item_type.generics.region_param_defs(); let raw_type = item_type.ty; // Generate the enum type. let regions = fcx.infcx().region_vars_for_defs(span, region_param_defs); - let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count); let substitutions = substs { regions: ty::NonerasedRegions(regions), self_ty: None, - tps: type_parameters + tps: fcx.infcx().next_ty_vars(item_type.generics.type_param_defs()) }; let enum_type = ty::subst(tcx, &substitutions, raw_type); @@ -2579,7 +2570,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, let v = ast_expr_vstore_to_vstore(fcx, ev, vst); let mut any_error = false; let mut any_bot = false; - let t: ty::t = fcx.infcx().next_ty_var(); + let t = fcx.infcx().next_ty_var(None); for e in args.iter() { check_expr_has_type(fcx, *e, t); let arg_t = fcx.expr_ty(*e); @@ -2622,7 +2613,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, _ => ast::MutImmutable, }; let tt = ast_expr_vstore_to_vstore(fcx, ev, vst); - let t = fcx.infcx().next_ty_var(); + let t = fcx.infcx().next_ty_var(None); check_expr_has_type(fcx, element, t); let arg_t = fcx.expr_ty(element); if ty::type_is_error(arg_t) { @@ -3142,7 +3133,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } } ast::ExprVec(ref args) => { - let t: ty::t = fcx.infcx().next_ty_var(); + let t: ty::t = fcx.infcx().next_ty_var(None); for e in args.iter() { check_expr_has_type(fcx, *e, t); } @@ -3153,7 +3144,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, ast::ExprRepeat(element, count_expr) => { check_expr_with_hint(fcx, count_expr, ty::mk_uint()); let count = ty::eval_repeat_count(fcx, count_expr); - let t: ty::t = fcx.infcx().next_ty_var(); + let t: ty::t = fcx.infcx().next_ty_var(None); check_expr_has_type(fcx, element, t); let element_ty = fcx.expr_ty(element); if ty::type_is_error(element_ty) { @@ -3845,11 +3836,11 @@ pub fn instantiate_path(fcx: &FnCtxt, // determine values for type parameters, using the values given by // the user (if any) and otherwise using fresh type variables let (tps, regions) = if ty_substs_len == 0 { - (fcx.infcx().next_ty_vars(ty_param_count), regions) + (fcx.infcx().next_ty_vars(tpt.generics.type_param_defs()), regions) } else if ty_param_count == 0 { fcx.ccx.tcx.sess.span_err (span, "this item does not take type parameters"); - (fcx.infcx().next_ty_vars(ty_param_count), regions) + (fcx.infcx().next_ty_vars(tpt.generics.type_param_defs()), regions) } else if ty_substs_len > user_ty_param_count { let expected = if user_ty_param_req < user_ty_param_count { "expected at most" @@ -3860,7 +3851,7 @@ pub fn instantiate_path(fcx: &FnCtxt, (span, format!("too many type parameters provided: {} {}, found {}", expected, user_ty_param_count, ty_substs_len)); - (fcx.infcx().next_ty_vars(ty_param_count), regions) + (fcx.infcx().next_ty_vars(tpt.generics.type_param_defs()), regions) } else if ty_substs_len < user_ty_param_req { let expected = if user_ty_param_req < user_ty_param_count { "expected at least" @@ -3871,7 +3862,7 @@ pub fn instantiate_path(fcx: &FnCtxt, (span, format!("not enough type parameters provided: {} {}, found {}", expected, user_ty_param_req, ty_substs_len)); - (fcx.infcx().next_ty_vars(ty_param_count), regions) + (fcx.infcx().next_ty_vars(tpt.generics.type_param_defs()), regions) } else { if ty_substs_len > user_ty_param_req && !fcx.tcx().sess.features.default_type_params.get() { @@ -3891,7 +3882,7 @@ pub fn instantiate_path(fcx: &FnCtxt, .enumerate() { match self_parameter_index { Some(index) if index == i => { - tps.push(*fcx.infcx().next_ty_vars(1).get(0)); + tps.push(fcx.infcx().next_ty_var(None)); pushed = true; } _ => {} @@ -3915,7 +3906,7 @@ pub fn instantiate_path(fcx: &FnCtxt, for (i, default) in defaults.skip(ty_substs_len).enumerate() { match self_parameter_index { Some(index) if index == i + ty_substs_len => { - substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0)); + substs.tps.push(fcx.infcx().next_ty_var(None)); pushed = true; } _ => {} @@ -3934,7 +3925,7 @@ pub fn instantiate_path(fcx: &FnCtxt, // If the self parameter goes at the end, insert it there. if !pushed && self_parameter_index.is_some() { - substs.tps.push(*fcx.infcx().next_ty_vars(1).get(0)) + substs.tps.push(fcx.infcx().next_ty_var(None)) } assert_eq!(substs.tps.len(), ty_param_count) diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 3a50b0681e8b8..136fddaa9d324 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -480,13 +480,10 @@ impl<'a> CoherenceChecker<'a> { infer::BoundRegionInCoherence(d.name))) .collect(); - let bounds_count = polytype.generics.type_param_defs().len(); - let type_parameters = self.inference_context.next_ty_vars(bounds_count); - let substitutions = substs { regions: ty::NonerasedRegions(region_parameters), self_ty: None, - tps: type_parameters + tps: self.inference_context.next_ty_vars(polytype.generics.type_param_defs()) }; let monotype = subst(self.crate_context.tcx, &substitutions, diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 54cf6524664c5..e613d94c17b84 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -69,15 +69,17 @@ use syntax::ast; use syntax::owned_slice::OwnedSlice; use syntax::abi; -pub trait Combine { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a>; - fn tag(&self) -> ~str; - fn a_is_expected(&self) -> bool; - fn trace(&self) -> TypeTrace; +pub trait Combine<'f> { + fn get_ref<'a>(&'a self) -> &'a CombineFields<'f>; + fn tag(&self) -> &'static str; - fn sub<'a>(&'a self) -> Sub<'a>; - fn lub<'a>(&'a self) -> Lub<'a>; - fn glb<'a>(&'a self) -> Glb<'a>; + fn infcx(&self) -> &'f InferCtxt<'f> { self.get_ref().infcx } + fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected } + fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() } + + fn sub(&self) -> Sub<'f> { Sub(self.get_ref().clone()) } + fn lub(&self) -> Lub<'f> { Lub(self.get_ref().clone()) } + fn glb(&self) -> Glb<'f> { Glb(self.get_ref().clone()) } fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres; fn contratys(&self, a: ty::t, b: ty::t) -> cres; @@ -131,11 +133,11 @@ pub trait Combine { as_: &ty::substs, bs: &ty::substs) -> cres { - fn relate_region_params(this: &C, - item_def_id: ast::DefId, - a: &ty::RegionSubsts, - b: &ty::RegionSubsts) - -> cres { + fn relate_region_params<'f, C: Combine<'f>>(this: &C, + item_def_id: ast::DefId, + a: &ty::RegionSubsts, + b: &ty::RegionSubsts) + -> cres { let tcx = this.infcx().tcx; match (a, b) { (&ty::ErasedRegions, _) | (_, &ty::ErasedRegions) => { @@ -331,7 +333,7 @@ pub struct CombineFields<'a> { pub trace: TypeTrace, } -pub fn expected_found( +pub fn expected_found<'f, C: Combine<'f>, T>( this: &C, a: T, b: T) -> ty::expected_found { if this.a_is_expected() { ty::expected_found {expected: a, found: b} @@ -340,15 +342,15 @@ pub fn expected_found( } } -pub fn eq_tys(this: &C, a: ty::t, b: ty::t) -> ures { +pub fn eq_tys<'f, C: Combine<'f>>(this: &C, a: ty::t, b: ty::t) -> ures { let suber = this.sub(); this.infcx().try(|| { suber.tys(a, b).and_then(|_ok| suber.contratys(a, b)).to_ures() }) } -pub fn eq_regions(this: &C, a: ty::Region, b: ty::Region) - -> ures { +pub fn eq_regions<'f, C: Combine<'f>>(this: &C, a: ty::Region, b: ty::Region) + -> ures { debug!("eq_regions({}, {})", a.repr(this.infcx().tcx), b.repr(this.infcx().tcx)); @@ -368,9 +370,11 @@ pub fn eq_regions(this: &C, a: ty::Region, b: ty::Region) }) } -pub fn super_fn_sigs(this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres { +pub fn super_fn_sigs<'f, C: Combine<'f>>(this: &C, a: &ty::FnSig, b: &ty::FnSig) + -> cres { - fn argvecs(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres > { + fn argvecs<'f, C: Combine<'f>>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) + -> cres > { if a_args.len() == b_args.len() { result::collect(a_args.iter().zip(b_args.iter()) .map(|(a, b)| this.args(*a, *b))) @@ -393,7 +397,7 @@ pub fn super_fn_sigs(this: &C, a: &ty::FnSig, b: &ty::FnSig) -> cres< variadic: a.variadic}) } -pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { +pub fn super_tys<'f, C: Combine<'f>>(this: &C, a: ty::t, b: ty::t) -> cres { let tcx = this.infcx().tcx; let a_sty = &ty::get(a).sty; let b_sty = &ty::get(b).sty; @@ -575,7 +579,7 @@ pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { _ => Err(ty::terr_sorts(expected_found(this, a, b))) }; - fn unify_integral_variable( + fn unify_integral_variable<'f, C: Combine<'f>>( this: &C, vid_is_expected: bool, vid: ty::IntVid, @@ -588,7 +592,7 @@ pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { } } - fn unify_float_variable( + fn unify_float_variable<'f, C: Combine<'f>>( this: &C, vid_is_expected: bool, vid: ty::FloatVid, diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 32bc7eedf2fcf..4ad2c85e98d26 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -15,11 +15,8 @@ use middle::ty; use middle::typeck::infer::then; use middle::typeck::infer::combine::*; use middle::typeck::infer::lattice::*; -use middle::typeck::infer::lub::Lub; -use middle::typeck::infer::sub::Sub; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::{cres, InferCtxt}; -use middle::typeck::infer::{TypeTrace, Subtype}; +use middle::typeck::infer::{cres, Subtype}; use middle::typeck::infer::fold_regions_in_sig; use syntax::ast::{Many, Once, MutImmutable, MutMutable}; use syntax::ast::{ExternFn, NormalFn, UnsafeFn, NodeId}; @@ -30,19 +27,9 @@ use util::ppaux::mt_to_str; pub struct Glb<'f>(pub CombineFields<'f>); // "greatest lower bound" (common subtype) -impl<'f> Glb<'f> { - pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Glb(ref v) = *self; v } -} - -impl<'f> Combine for Glb<'f> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx } - fn tag(&self) -> ~str { "glb".to_owned() } - fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected } - fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() } - - fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) } - fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) } - fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) } +impl<'f> Combine<'f> for Glb<'f> { + fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Glb(ref v) = *self; v } + fn tag(&self) -> &'static str { "glb" } fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres { let tcx = self.get_ref().infcx.tcx; diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index ebfb17a887633..a04968ba797e8 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -71,19 +71,19 @@ impl LatticeValue for ty::t { } pub trait CombineFieldsLatticeMethods { - fn var_sub_var>>(&self, a_id: V, b_id: V) -> ures; /// make variable a subtype of T - fn var_sub_t>>( &self, a_id: V, b: T) -> ures; - fn t_sub_var>>( &self, a: T, @@ -95,7 +95,7 @@ pub trait CombineFieldsLatticeMethods { b: &Bound, lattice_op: LatticeOp) -> cres>; - fn set_var_to_merged_bounds>>( &self, v_id: V, @@ -111,7 +111,7 @@ pub trait CombineFieldsLatticeMethods { } impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { - fn var_sub_var>>( &self, a_id: V, @@ -164,7 +164,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { } /// make variable a subtype of T - fn var_sub_t>>( &self, a_id: V, @@ -177,7 +177,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { let node_a = self.infcx.get(a_id); let a_id = node_a.root.clone(); let a_bounds = &node_a.possible_types; - let b_bounds = &Bounds { lb: None, ub: Some(b.clone()) }; + let b_bounds = &Bounds { lb: None, ub: Some(b.clone()), fallback: None }; debug!("var_sub_t({}={} <: {})", a_id.to_str(), @@ -188,7 +188,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { a_id, a_bounds, b_bounds, node_a.rank) } - fn t_sub_var>>( &self, a: T, @@ -198,7 +198,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { * * Make a concrete type (`a`) a subtype of the variable `b_id` */ - let a_bounds = &Bounds { lb: Some(a.clone()), ub: None }; + let a_bounds = &Bounds { lb: Some(a.clone()), ub: None, fallback: None }; let node_b = self.infcx.get(b_id); let b_id = node_b.root.clone(); let b_bounds = &node_b.possible_types; @@ -237,7 +237,7 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { } } - fn set_var_to_merged_bounds>>( &self, v_id: V, @@ -287,7 +287,21 @@ impl<'f> CombineFieldsLatticeMethods for CombineFields<'f> { let () = if_ok!(self.bnds(&b.lb, &a.ub)); let ub = if_ok!(self.merge_bnd(&a.ub, &b.ub, LatticeValue::glb)); let lb = if_ok!(self.merge_bnd(&a.lb, &b.lb, LatticeValue::lub)); - let bounds = Bounds { lb: lb, ub: ub }; + + let fallback = match (&a.fallback, &b.fallback) { + (&None, &None) => None, + (&Some(ref t), &None) | (&None, &Some(ref t)) => Some(t.clone()), + (&Some(ref a), &Some(ref b)) => { + if a == b { + Some(a.clone()) + } else { + // Is there anything we could do to combine a and b? + None + } + } + }; + + let bounds = Bounds { lb: lb, ub: ub, fallback: fallback }; debug!("merge({}): bounds={}", v_id.to_str(), bounds.inf_str(self.infcx)); @@ -364,10 +378,10 @@ impl<'f> TyLatticeDir for Glb<'f> { } } -pub fn super_lattice_tys(this: &L, - a: ty::t, - b: ty::t) - -> cres { +pub fn super_lattice_tys<'f, L:LatticeDir+TyLatticeDir+Combine<'f>>(this: &L, + a: ty::t, + b: ty::t) + -> cres { debug!("{}.lattice_tys({}, {})", this.tag(), a.inf_str(this.infcx()), b.inf_str(this.infcx())); @@ -430,8 +444,8 @@ pub enum LatticeVarResult { * the variables and return the unified variable, in which case the * result is a variable. This is indicated with a `VarResult` * return. */ -pub fn lattice_vars, + T:Clone + Eq + InferStr + LatticeValue, V:Clone + Eq + ToStr + Vid + UnifyVid>>( this: &L, // defines whether we want LUB or GLB a_vid: V, // first variable @@ -476,7 +490,7 @@ pub fn lattice_vars, T:Clone + InferStr + LatticeValue, V:Clone + Eq + ToStr + Vid + UnifyVid>>( this: &L, @@ -521,9 +535,9 @@ pub fn lattice_var_and_t(this: &T, - map: &HashMap) - -> Vec { +pub fn var_ids<'f, T: Combine<'f>>(this: &T, + map: &HashMap) + -> Vec { map.iter().map(|(_, r)| match *r { ty::ReInfer(ty::ReVar(r)) => { r } r => { diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index d09bbc4253ba9..fe3034edc037f 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -14,13 +14,10 @@ use middle::ty::RegionVid; use middle::ty; use middle::typeck::infer::then; use middle::typeck::infer::combine::*; -use middle::typeck::infer::glb::Glb; use middle::typeck::infer::lattice::*; -use middle::typeck::infer::sub::Sub; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::{cres, InferCtxt}; +use middle::typeck::infer::{cres, Subtype}; use middle::typeck::infer::fold_regions_in_sig; -use middle::typeck::infer::{TypeTrace, Subtype}; use collections::HashMap; use syntax::ast::{Many, Once, NodeId}; use syntax::ast::{ExternFn, NormalFn, UnsafeFn}; @@ -29,19 +26,9 @@ use util::ppaux::mt_to_str; pub struct Lub<'f>(pub CombineFields<'f>); // least-upper-bound: common supertype -impl<'f> Lub<'f> { - pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v } -} - -impl<'f> Combine for Lub<'f> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx } - fn tag(&self) -> ~str { "lub".to_owned() } - fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected } - fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() } - - fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) } - fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) } - fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) } +impl<'f> Combine<'f> for Lub<'f> { + fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Lub(ref v) = *self; v } + fn tag(&self) -> &'static str { "lub" } fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres { let tcx = self.get_ref().infcx.tcx; diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 258f286d8f025..8812b6b73d8fe 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -66,7 +66,8 @@ pub type Bound = Option; #[deriving(Clone)] pub struct Bounds { lb: Bound, - ub: Bound + ub: Bound, + fallback: Bound } pub type cres = Result; // "combine result" @@ -590,23 +591,22 @@ fn next_simple_var(counter: &mut uint, } impl<'a> InferCtxt<'a> { - pub fn next_ty_var_id(&self) -> TyVid { + pub fn next_ty_var(&self, fallback: Option) -> ty::t { let id = self.ty_var_counter.get(); self.ty_var_counter.set(id + 1); - { - let mut ty_var_bindings = self.ty_var_bindings.borrow_mut(); - let vals = &mut ty_var_bindings.vals; - vals.insert(id, Root(Bounds { lb: None, ub: None }, 0u)); - } - return TyVid(id); - } + self.ty_var_bindings.borrow_mut().vals.insert(id, Root(Bounds { + lb: None, + ub: None, + fallback: fallback + }, 0u)); - pub fn next_ty_var(&self) -> ty::t { - ty::mk_var(self.tcx, self.next_ty_var_id()) + ty::mk_var(self.tcx, TyVid(id)) } - pub fn next_ty_vars(&self, n: uint) -> Vec { - Vec::from_fn(n, |_i| self.next_ty_var()) + pub fn next_ty_vars(&self, ty_params: &[ty::TypeParameterDef]) -> Vec { + ty_params.iter().map(|ty_param| { + self.next_ty_var(ty_param.default) + }).collect() } pub fn next_int_var_id(&self) -> IntVid { diff --git a/src/librustc/middle/typeck/infer/resolve.rs b/src/librustc/middle/typeck/infer/resolve.rs index 9df610dc7bc2a..90b9fb76c9500 100644 --- a/src/librustc/middle/typeck/infer/resolve.rs +++ b/src/librustc/middle/typeck/infer/resolve.rs @@ -220,11 +220,14 @@ impl<'a> ResolveState<'a> { let bounds = nde.possible_types; let t1 = match bounds { - Bounds { ub:_, lb:Some(t) } if !type_is_bot(t) + Bounds { ub:_, lb:Some(t), .. } if !type_is_bot(t) => self.resolve_type(t), - Bounds { ub:Some(t), lb:_ } => self.resolve_type(t), - Bounds { ub:_, lb:Some(t) } => self.resolve_type(t), - Bounds { ub:None, lb:None } => { + Bounds { ub:Some(t), lb:_, .. } => self.resolve_type(t), + Bounds { ub:_, lb:Some(t), .. } => self.resolve_type(t), + Bounds { ub:None, lb:None, fallback: Some(t) } if self.should(force_tvar) => { + self.resolve_type(t) + } + Bounds { ub:None, lb:None, .. } => { if self.should(force_tvar) { self.err = Some(unresolved_ty(vid)); } diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 2c8acd0573b74..d918b2245e671 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -14,14 +14,10 @@ use middle::ty; use middle::ty::TyVar; use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig; use middle::typeck::infer::combine::*; -use middle::typeck::infer::{cres, CresCompare}; -use middle::typeck::infer::glb::Glb; -use middle::typeck::infer::InferCtxt; +use middle::typeck::infer::{cres, CresCompare, Subtype}; use middle::typeck::infer::lattice::CombineFieldsLatticeMethods; -use middle::typeck::infer::lub::Lub; use middle::typeck::infer::then; use middle::typeck::infer::to_str::InferStr; -use middle::typeck::infer::{TypeTrace, Subtype}; use util::common::{indenter}; use util::ppaux::bound_region_to_str; @@ -29,19 +25,9 @@ use syntax::ast::{Onceness, FnStyle}; pub struct Sub<'f>(pub CombineFields<'f>); // "subtype", "subregion" etc -impl<'f> Sub<'f> { - pub fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Sub(ref v) = *self; v } -} - -impl<'f> Combine for Sub<'f> { - fn infcx<'a>(&'a self) -> &'a InferCtxt<'a> { self.get_ref().infcx } - fn tag(&self) -> ~str { "sub".to_owned() } - fn a_is_expected(&self) -> bool { self.get_ref().a_is_expected } - fn trace(&self) -> TypeTrace { self.get_ref().trace.clone() } - - fn sub<'a>(&'a self) -> Sub<'a> { Sub(self.get_ref().clone()) } - fn lub<'a>(&'a self) -> Lub<'a> { Lub(self.get_ref().clone()) } - fn glb<'a>(&'a self) -> Glb<'a> { Glb(self.get_ref().clone()) } +impl<'f> Combine<'f> for Sub<'f> { + fn get_ref<'a>(&'a self) -> &'a CombineFields<'f> { let Sub(ref v) = *self; v } + fn tag(&self) -> &'static str { "sub" } fn contratys(&self, a: ty::t, b: ty::t) -> cres { let opp = CombineFields {