diff --git a/src/librustc/middle/infer/bivariate.rs b/src/librustc/middle/infer/bivariate.rs index 2d9432b75e719..1877fad9c1c09 100644 --- a/src/librustc/middle/infer/bivariate.rs +++ b/src/librustc/middle/infer/bivariate.rs @@ -30,7 +30,7 @@ use super::type_variable::{BiTo}; use middle::ty::{self, Ty}; use middle::ty::TyVar; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; pub struct Bivariate<'a, 'tcx: 'a> { fields: CombineFields<'a, 'tcx> @@ -74,7 +74,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } + if a == b { return Ok(RelateOk::from(a)); } let infcx = self.fields.infcx; let a = infcx.type_variables.borrow().replace_if_possible(a); @@ -82,17 +82,15 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { match (&a.sty, &b.sty) { (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id); - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(TyVar(a_id)), _) => { - try!(self.fields.instantiate(b, BiTo, a_id)); - Ok(a) + self.fields.instantiate(b, BiTo, a_id).map_value(|_| a) } (_, &ty::TyInfer(TyVar(b_id))) => { - try!(self.fields.instantiate(a, BiTo, b_id)); - Ok(a) + self.fields.instantiate(a, BiTo, b_id).map_value(|_| a) } _ => { @@ -102,7 +100,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { } fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> { - Ok(a) + Ok(RelateOk::from(a)) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) @@ -111,7 +109,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { { let a1 = self.tcx().erase_late_bound_regions(a); let b1 = self.tcx().erase_late_bound_regions(b); - let c = try!(self.relate(&a1, &b1)); - Ok(ty::Binder(c)) + self.relate(&a1, &b1).map_value(|c| ty::Binder(c)) } } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index faf1bdb0ce504..ec8876a89ef67 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -45,7 +45,7 @@ use middle::ty::{IntType, UintType}; use middle::ty::{self, Ty}; use middle::ty::error::TypeError; use middle::ty::fold::{TypeFolder, TypeFoldable}; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, TypeRelation}; use syntax::ast; use syntax::codemap::Span; @@ -74,7 +74,7 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>, .borrow_mut() .unify_var_var(a_id, b_id) .map_err(|e| int_unification_error(a_is_expected, e))); - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => { unify_integral_variable(infcx, a_is_expected, v_id, IntType(v)) @@ -95,7 +95,7 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>, .borrow_mut() .unify_var_var(a_id, b_id) .map_err(|e| float_unification_error(relation.a_is_expected(), e))); - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => { unify_float_variable(infcx, a_is_expected, v_id, v) @@ -129,8 +129,8 @@ fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, .unify_var_value(vid, val) .map_err(|e| int_unification_error(vid_is_expected, e))); match val { - IntType(v) => Ok(infcx.tcx.mk_mach_int(v)), - UintType(v) => Ok(infcx.tcx.mk_mach_uint(v)), + IntType(v) => Ok(RelateOk::from(infcx.tcx.mk_mach_int(v))), + UintType(v) => Ok(RelateOk::from(infcx.tcx.mk_mach_uint(v))), } } @@ -145,7 +145,7 @@ fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>, .borrow_mut() .unify_var_value(vid, val) .map_err(|e| float_unification_error(vid_is_expected, e))); - Ok(infcx.tcx.mk_mach_float(val)) + Ok(RelateOk::from(infcx.tcx.mk_mach_float(val))) } impl<'a, 'tcx> CombineFields<'a, 'tcx> { @@ -187,6 +187,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { -> RelateResult<'tcx, ()> { let mut stack = Vec::new(); + let mut obligations = Vec::new(); stack.push((a_ty, dir, b_vid)); loop { // For each turn of the loop, we extract a tuple @@ -224,10 +225,11 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { Some(t) => t, // ...already instantiated. None => { // ...not yet instantiated: // Generalize type if necessary. - let generalized_ty = try!(match dir { - EqTo => self.generalize(a_ty, b_vid, false), - BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true), - }); + let RelateOk { value: generalized_ty, obligations: new_obligations } = + try!(match dir { + EqTo => self.generalize(a_ty, b_vid, false), + BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true), + }); debug!("instantiate(a_ty={:?}, dir={:?}, \ b_vid={:?}, generalized_ty={:?})", a_ty, dir, b_vid, @@ -236,6 +238,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { .borrow_mut() .instantiate_and_push( b_vid, generalized_ty, &mut stack); + obligations.extend(new_obligations); generalized_ty } }; @@ -247,15 +250,16 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // relations wind up attributed to the same spans. We need // to associate causes/spans with each of the relations in // the stack to get this right. - try!(match dir { + let RelateOk { obligations: new_obligations, .. } = try!(match dir { BiTo => self.bivariate().relate(&a_ty, &b_ty), EqTo => self.equate().relate(&a_ty, &b_ty), SubtypeOf => self.sub().relate(&a_ty, &b_ty), SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty), }); + obligations.extend(new_obligations); } - Ok(()) + Ok(RelateOk { value: (), obligations: obligations }) } /// Attempts to generalize `ty` for the type variable `for_vid`. This checks for cycle -- that @@ -279,7 +283,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { if generalize.cycle_detected { Err(TypeError::CyclicTy) } else { - Ok(u) + Ok(RelateOk::from(u)) } } } @@ -370,7 +374,7 @@ impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'t F: FnOnce() -> TypeError<'tcx>, { self.clone().and_then(|s| { - if s == t { + if s.value == t { self.clone() } else { Err(f()) diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index d1dad4921ae21..23d42de3b7442 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -15,7 +15,7 @@ use super::type_variable::{EqTo}; use middle::ty::{self, Ty}; use middle::ty::TyVar; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; /// Ensures `a` is made equal to `b`. Returns `a` on success. pub struct Equate<'a, 'tcx: 'a> { @@ -47,7 +47,7 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } + if a == b { return Ok(RelateOk::from(a)); } let infcx = self.fields.infcx; let a = infcx.type_variables.borrow().replace_if_possible(a); @@ -55,22 +55,19 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { match (&a.sty, &b.sty) { (&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id); - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(TyVar(a_id)), _) => { - try!(self.fields.instantiate(b, EqTo, a_id)); - Ok(a) + self.fields.instantiate(b, EqTo, a_id).map_value(|_| a) } (_, &ty::TyInfer(TyVar(b_id))) => { - try!(self.fields.instantiate(a, EqTo, b_id)); - Ok(a) + self.fields.instantiate(a, EqTo, b_id).map_value(|_| a) } _ => { - try!(combine::super_combine_tys(self.fields.infcx, self, a, b)); - Ok(a) + combine::super_combine_tys(self.fields.infcx, self, a, b).map_value(|_| a) } } } @@ -82,14 +79,14 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { b); let origin = Subtype(self.fields.trace.clone()); self.fields.infcx.region_vars.make_eqregion(origin, a, b); - Ok(a) + Ok(RelateOk::from(a)) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) -> RelateResult<'tcx, ty::Binder> where T: Relate<'a, 'tcx> { - try!(self.fields.higher_ranked_sub(a, b)); - self.fields.higher_ranked_sub(b, a) + self.fields.higher_ranked_sub(a, b) + .and_then_with(|_| self.fields.higher_ranked_sub(b, a)) } } diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index 0035f31e8db94..6bbb9580dc10b 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -15,7 +15,7 @@ use super::lattice::{self, LatticeDir}; use super::Subtype; use middle::ty::{self, Ty}; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; /// "Greatest lower bound" (common subtype) pub struct Glb<'a, 'tcx: 'a> { @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> { b); let origin = Subtype(self.fields.trace.clone()); - Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b)) + Ok(RelateOk::from(self.fields.infcx.region_vars.glb_regions(origin, a, b))) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) @@ -78,8 +78,8 @@ impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> { fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(); - try!(sub.relate(&v, &a)); - try!(sub.relate(&v, &b)); - Ok(()) + sub.relate(&v, &a) + .and_then_with(|_| sub.relate(&v, &b)) + .and_then_with(|_| Ok(RelateOk::from(()))) } } diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index e8f542db933cb..0a44d2c500379 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -16,7 +16,7 @@ use super::combine::CombineFields; use middle::ty::{self, Binder, TypeFoldable}; use middle::ty::error::TypeError; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; use syntax::codemap::Span; use util::nodemap::{FnvHashMap, FnvHashSet}; @@ -97,7 +97,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { debug!("higher_ranked_sub: OK result={:?}", result); - Ok(ty::Binder(result)) + Ok(result).map_value(|r| ty::Binder(r)) }); } @@ -117,7 +117,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { span, HigherRankedType, b); // Collect constraints. - let result0 = + let RelateOk { value: result0, obligations } = try!(self.lub().relate(&a_with_fresh, &b_with_fresh)); let result0 = self.infcx.resolve_type_vars_if_possible(&result0); @@ -138,7 +138,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(RelateOk { value: ty::Binder(result1), obligations: obligations }) }); fn generalize_region(infcx: &InferCtxt, @@ -211,7 +211,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { let b_vars = var_ids(self, &b_map); // Collect constraints. - let result0 = + let RelateOk { value: result0, obligations } = try!(self.glb().relate(&a_with_fresh, &b_with_fresh)); let result0 = self.infcx.resolve_type_vars_if_possible(&result0); @@ -234,7 +234,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { b, result1); - Ok(ty::Binder(result1)) + Ok(RelateOk { value: ty::Binder(result1), obligations: obligations }) }); fn generalize_region(infcx: &InferCtxt, diff --git a/src/librustc/middle/infer/lattice.rs b/src/librustc/middle/infer/lattice.rs index 2a560ec8a1d23..8f01d52dbe886 100644 --- a/src/librustc/middle/infer/lattice.rs +++ b/src/librustc/middle/infer/lattice.rs @@ -34,7 +34,7 @@ use super::InferCtxt; use middle::ty::TyVar; use middle::ty::{self, Ty}; -use middle::ty::relate::{RelateResult, TypeRelation}; +use middle::ty::relate::{RelateOk, RelateResult, RelateResultTrait, TypeRelation}; pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> { fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; @@ -56,7 +56,7 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L, b); if a == b { - return Ok(a); + return Ok(RelateOk::from(a)); } let infcx = this.infcx(); @@ -66,15 +66,13 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L, (&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..))) if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => { let v = infcx.next_diverging_ty_var(); - try!(this.relate_bound(v, a, b)); - Ok(v) + this.relate_bound(v, a, b).map_value(|_| v) } (&ty::TyInfer(TyVar(..)), _) | (_, &ty::TyInfer(TyVar(..))) => { let v = infcx.next_ty_var(); - try!(this.relate_bound(v, a, b)); - Ok(v) + this.relate_bound(v, a, b).map_value(|_| v) } _ => { diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index 238dad65ef0d9..4684aba99c79d 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -15,7 +15,7 @@ use super::lattice::{self, LatticeDir}; use super::Subtype; use middle::ty::{self, Ty}; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; /// "Least upper bound" (common supertype) pub struct Lub<'a, 'tcx: 'a> { @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> { b); let origin = Subtype(self.fields.trace.clone()); - Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b)) + Ok(RelateOk::from(self.fields.infcx.region_vars.lub_regions(origin, a, b))) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) @@ -78,8 +78,8 @@ impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> { fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { let mut sub = self.fields.sub(); - try!(sub.relate(&a, &v)); - try!(sub.relate(&b, &v)); - Ok(()) + sub.relate(&a, &v) + .and_then_with(|_| sub.relate(&b, &v)) + .and_then_with(|_| Ok(RelateOk::from(()))) } } diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 26ea5454693e1..e72979b1583a6 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -33,7 +33,7 @@ use middle::ty::{TyVid, IntVid, FloatVid}; use middle::ty::{self, Ty}; use middle::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use middle::ty::fold::{TypeFolder, TypeFoldable}; -use middle::ty::relate::{Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{RefCell, Ref}; use std::fmt; @@ -385,7 +385,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a_is_expected: bool, a: Ty<'tcx>, b: Ty<'tcx>) - -> Ty<'tcx> + -> RelateOk<'tcx, Ty<'tcx>> { debug!("common_supertype({:?}, {:?})", a, b); @@ -400,7 +400,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, Ok(t) => t, Err(ref err) => { cx.report_and_explain_type_error(trace, err); - cx.tcx.types.err + RelateOk::from(cx.tcx.types.err) } } } @@ -426,7 +426,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin::Misc(codemap::DUMMY_SP), values: Types(expected_found(true, a, b)) }; - cx.sub(true, trace).relate(&a, &b).map(|_| ()) + cx.sub(true, trace).relate(&a, &b).map_value(|_| ()) }) } @@ -835,7 +835,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("sub_types({:?} <: {:?})", a, b); self.commit_if_ok(|_| { let trace = TypeTrace::types(origin, a_is_expected, a, b); - self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) + self.sub(a_is_expected, trace).relate(&a, &b).map_value(|_| ()) }) } @@ -848,7 +848,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { self.commit_if_ok(|_| { let trace = TypeTrace::types(origin, a_is_expected, a, b); - self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ()) + self.equate(a_is_expected, trace).relate(&a, &b).map_value(|_| ()) }) } @@ -867,7 +867,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: origin, values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) }; - self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ()) + self.equate(a_is_expected, trace).relate(&a, &b).map_value(|_| ()) }) } @@ -886,7 +886,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: origin, values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) }; - self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ()) + self.sub(a_is_expected, trace).relate(&a, &b).map_value(|_| ()) }) } @@ -909,7 +909,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /*! See `higher_ranked::leak_check` */ match higher_ranked::leak_check(self, skol_map, snapshot) { - Ok(()) => Ok(()), + Ok(()) => Ok(RelateOk::from(())), Err((br, r)) => Err(TypeError::RegionsInsufficientlyPolymorphic(br, r)) } } @@ -934,8 +934,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let (ty::EquatePredicate(a, b), skol_map) = self.skolemize_late_bound_regions(predicate, snapshot); let origin = TypeOrigin::EquatePredicate(span); - let () = try!(mk_eqty(self, false, origin, a, b)); - self.leak_check(&skol_map, snapshot) + mk_eqty(self, false, origin, a, b) + .and_then_with(|_| self.leak_check(&skol_map, snapshot)) }) } @@ -1426,7 +1426,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { values: Types(expected_found(true, e, e)) }; self.equate(true, trace).relate(a, b) - }).map(|_| ()) + }).map_value(|_| ()) } pub fn node_ty(&self, id: ast::NodeId) -> McResult> { diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index 2cd686fde156e..3398652b2055e 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -15,7 +15,7 @@ use super::type_variable::{SubtypeOf, SupertypeOf}; use middle::ty::{self, Ty}; use middle::ty::TyVar; -use middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use middle::ty::relate::{Cause, Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -62,7 +62,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } + if a == b { return Ok(RelateOk::from(a)); } let infcx = self.fields.infcx; let a = infcx.type_variables.borrow().replace_if_possible(a); @@ -72,26 +72,23 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { infcx.type_variables .borrow_mut() .relate_vars(a_id, SubtypeOf, b_id); - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(TyVar(a_id)), _) => { - try!(self.fields - .switch_expected() - .instantiate(b, SupertypeOf, a_id)); - Ok(a) + self.fields + .switch_expected() + .instantiate(b, SupertypeOf, a_id).map_value(|_| a) } (_, &ty::TyInfer(TyVar(b_id))) => { - try!(self.fields.instantiate(a, SubtypeOf, b_id)); - Ok(a) + self.fields.instantiate(a, SubtypeOf, b_id).map_value(|_| a) } (&ty::TyError, _) | (_, &ty::TyError) => { - Ok(self.tcx().types.err) + Ok(RelateOk::from(self.tcx().types.err)) } _ => { - try!(combine::super_combine_tys(self.fields.infcx, self, a, b)); - Ok(a) + combine::super_combine_tys(self.fields.infcx, self, a, b).map_value(|_| a) } } } @@ -104,7 +101,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { // error messages. let origin = SubregionOrigin::Subtype(self.fields.trace.clone()); self.fields.infcx.region_vars.make_subregion(origin, a, b); - Ok(a) + Ok(RelateOk::from(a)) } fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index de70cdbd29a35..b4eb3a2b46d47 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -11,6 +11,7 @@ use dep_graph::DepGraph; use middle::infer::InferCtxt; use middle::ty::{self, Ty, TypeFoldable, ToPolyTraitRef}; +use middle::ty::relate::RelateOk; use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error}; use std::iter; use syntax::ast; @@ -526,14 +527,14 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>, ty::Predicate::Equate(ref binder) => { match selcx.infcx().equality_predicate(obligation.cause.span, binder) { - Ok(()) => Ok(Some(Vec::new())), + Ok(RelateOk { obligations, .. }) => Ok(Some(obligations)), Err(_) => Err(CodeSelectionError(Unimplemented)), } } ty::Predicate::RegionOutlives(ref binder) => { match selcx.infcx().region_outlives_predicate(obligation.cause.span, binder) { - Ok(()) => Ok(Some(Vec::new())), + Ok(RelateOk { obligations, .. }) => Ok(Some(obligations)), Err(_) => Err(CodeSelectionError(Unimplemented)), } } diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c363425db85b0..31bb1506cacb9 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -25,6 +25,7 @@ use middle::infer::{self, TypeOrigin}; use middle::subst::Subst; use middle::ty::{self, ToPredicate, ToPolyTraitRef, Ty}; use middle::ty::fold::{TypeFoldable, TypeFolder}; +use middle::ty::relate::RelateOk; use syntax::parse::token; use util::common::FN_OUTPUT_NAME; @@ -97,7 +98,14 @@ pub fn poly_project_and_unify_type<'cx,'tcx>( match project_and_unify_type(selcx, &skol_obligation) { Ok(result) => { match infcx.leak_check(&skol_map, snapshot) { - Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, &result)), + Ok(RelateOk { obligations, .. }) => Ok({ + if let Some(mut x) = infcx.plug_leaks(skol_map, snapshot, &result) { + x.extend(obligations); + Some(x) + } else { + None + } + }), Err(e) => Err(MismatchedProjectionTypes { err: e }), } } @@ -121,7 +129,7 @@ fn project_and_unify_type<'cx,'tcx>( debug!("project_and_unify_type(obligation={:?})", obligation); - let Normalized { value: normalized_ty, obligations } = + let Normalized { value: normalized_ty, mut obligations } = match opt_normalize_projection_type(selcx, obligation.predicate.projection_ty.clone(), obligation.cause.clone(), @@ -140,7 +148,10 @@ fn project_and_unify_type<'cx,'tcx>( let infcx = selcx.infcx(); let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); match infer::mk_eqty(infcx, true, origin, normalized_ty, obligation.predicate.ty) { - Ok(()) => Ok(Some(obligations)), + Ok(RelateOk { obligations: mk_obligations, .. }) => { + obligations.extend(mk_obligations); + Ok(Some(obligations)) + }, Err(err) => Err(MismatchedProjectionTypes { err: err }), } } @@ -185,10 +196,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext ret_type); let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); let obligation_ty = obligation.predicate.ty; - match infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type) { - Ok(()) => { } - Err(_) => { /* ignore errors */ } - } + let _ = infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type); } _ => { } } @@ -921,7 +929,8 @@ fn confirm_param_env_candidate<'cx,'tcx>( origin, obligation.predicate.trait_ref.clone(), projection.projection_ty.trait_ref.clone()) { - Ok(()) => { } + // Do RelateOk predicates need to be propagated here? + Ok(_) => { } Err(e) => { selcx.tcx().sess.span_bug( obligation.cause.span, diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 29355e0684d96..3ad095af28a34 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -476,7 +476,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Predicate::Equate(ref p) => { // does this code ever run? match self.infcx.equality_predicate(obligation.cause.span, p) { - Ok(()) => EvaluatedToOk, + // Do we need to somehow propagate obligations here? + Ok(_) => EvaluatedToOk, Err(_) => EvaluatedToErr } } @@ -1164,7 +1165,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { origin, trait_bound.clone(), ty::Binder(skol_trait_ref.clone())) { - Ok(()) => { } + // Do we need to somehow propagate obligations here? + Ok(_) => { } Err(_) => { return false; } } @@ -2453,7 +2455,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { origin, expected_trait_ref.clone(), obligation_trait_ref.clone()) { - Ok(()) => Ok(()), + // Do we need to somehow propagate obligations here? + Ok(_) => Ok(()), Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } } @@ -2770,7 +2773,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { origin, poly_trait_ref, obligation.predicate.to_poly_trait_ref()) { - Ok(()) => Ok(()), + // Do we need to somehow propagate obligations here? + Ok(_) => Ok(()), Err(_) => Err(()), } } diff --git a/src/librustc/middle/ty/_match.rs b/src/librustc/middle/ty/_match.rs index 5a3ad9095ad2c..0f3e1f7eb0fd4 100644 --- a/src/librustc/middle/ty/_match.rs +++ b/src/librustc/middle/ty/_match.rs @@ -10,7 +10,7 @@ use middle::ty::{self, Ty}; use middle::ty::error::TypeError; -use middle::ty::relate::{self, Relate, TypeRelation, RelateResult}; +use middle::ty::relate::{self, Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation}; /// A type "A" *matches* "B" if the fresh types in B could be /// substituted with values so as to make it equal to A. Matching is @@ -57,19 +57,19 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { self.tag(), a, b); - Ok(a) + Ok(RelateOk::from(a)) } fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); - if a == b { return Ok(a); } + if a == b { return Ok(RelateOk::from(a)); } match (&a.sty, &b.sty) { (_, &ty::TyInfer(ty::FreshTy(_))) | (_, &ty::TyInfer(ty::FreshIntTy(_))) | (_, &ty::TyInfer(ty::FreshFloatTy(_))) => { - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyInfer(_), _) | @@ -78,7 +78,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { } (&ty::TyError, _) | (_, &ty::TyError) => { - Ok(self.tcx().types.err) + Ok(RelateOk::from(self.tcx().types.err)) } _ => { @@ -91,6 +91,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { -> RelateResult<'tcx, ty::Binder> where T: Relate<'a,'tcx> { - Ok(ty::Binder(try!(self.relate(a.skip_binder(), b.skip_binder())))) + self.relate(a.skip_binder(), b.skip_binder()).map_value(|c| ty::Binder(c)) } } diff --git a/src/librustc/middle/ty/relate.rs b/src/librustc/middle/ty/relate.rs index 974b5c4bc6c2a..ef3dd3f087c82 100644 --- a/src/librustc/middle/ty/relate.rs +++ b/src/librustc/middle/ty/relate.rs @@ -13,15 +13,105 @@ //! can be other things. Examples of type relations are subtyping, //! type equality, etc. +use std::cell::Cell; +use std::iter::FromIterator; + use middle::def_id::DefId; use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs}; +use middle::traits; use middle::ty::{self, Ty, TypeFoldable}; use middle::ty::error::{ExpectedFound, TypeError}; use std::rc::Rc; use syntax::abi; use rustc_front::hir as ast; -pub type RelateResult<'tcx, T> = Result>; + +#[derive(Clone, Debug)] +pub struct RelateOk<'tcx, T> { + pub value: T, + pub obligations: Vec>, +} +impl<'tcx, T> From for RelateOk<'tcx, T> { + fn from(value: T) -> Self { + RelateOk { value: value, obligations: Vec::new() } + } +} +impl<'tcx, T> RelateOk<'tcx, T> { + pub fn chain(self, other: RelateOk<'tcx, U>) -> RelateOk<'tcx, (T, U)> { + let RelateOk { value, mut obligations } = self; + let RelateOk { value: other_value, obligations: other_obligations } = other; + obligations.extend(other_obligations); + RelateOk { value: (value, other_value), obligations: obligations } + } +} + +pub type RelateResult<'tcx, T> = Result, TypeError<'tcx>>; + +pub trait RelateResultTrait<'tcx, T> { + fn map_value U>(self, mapper: F) -> RelateResult<'tcx, U>; + fn and_then_with RelateResult<'tcx, U>>(self, mapper: F) + -> RelateResult<'tcx, U>; +} +impl<'tcx, T> RelateResultTrait<'tcx, T> for RelateResult<'tcx, T> { + fn map_value U>(self, mapper: F) -> RelateResult<'tcx, U> { + match self { + Ok(RelateOk { value, obligations }) => + Ok(RelateOk{ value: mapper(value), obligations: obligations }), + Err(x) => Err(x), + } + } + fn and_then_with RelateResult<'tcx, U>>(self, mapper: F) + -> RelateResult<'tcx, U> + { + match self { + Ok(RelateOk { value, mut obligations }) => match mapper(value) { + Ok(RelateOk { value: next_value, obligations: new_obligations }) => { + obligations.extend(new_obligations); + Ok(RelateOk { value: next_value, obligations: obligations }) + }, + Err(x) => Err(x), + }, + Err(x) => Err(x), + } + } +} +fn relate_result_from_iter<'tcx, T, U, I: IntoIterator>>(iter: I) + -> RelateResult<'tcx, T> where T: FromIterator +{ + let mut all_obligations = Vec::new(); + let mut err = None; + let end_on_next_elem = Cell::new(false); + let value = iter.into_iter() + .take_while(|x| { + if end_on_next_elem.get() { + false + } else { + if !x.is_ok() { + end_on_next_elem.set(true); + } + true + } + }) + .filter_map(|x| { + match x { + Ok(RelateOk { value, obligations }) => { + all_obligations.extend(obligations); + Some(value) + }, + Err(x) => { + err = Some(x); + None + }, + } + }) + .collect(); + match err { + Some(err) => Err(err), + None => { + Ok(RelateOk { value: value, obligations: all_obligations }) + } + } +} #[derive(Clone, Debug)] pub enum Cause { @@ -52,7 +142,8 @@ pub trait TypeRelation<'a,'tcx> : Sized { /// Relete elements of two slices pairwise. fn relate_zip>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec> { assert_eq!(a.len(), b.len()); - a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect() + let tmp: Vec<_> = a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect(); + relate_result_from_iter(tmp) } /// Switch variance for the purpose of relating `a` and `b`. @@ -108,8 +199,8 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TypeAndMut<'tcx> { ast::Mutability::MutImmutable => ty::Covariant, ast::Mutability::MutMutable => ty::Invariant, }; - let ty = try!(relation.relate_with_variance(variance, &a.ty, &b.ty)); - Ok(ty::TypeAndMut {ty: ty, mutbl: mutbl}) + relation.relate_with_variance(variance, &a.ty, &b.ty) + .map_value(|ty| ty::TypeAndMut {ty: ty, mutbl: mutbl}) } } } @@ -147,12 +238,15 @@ fn relate_substs<'a,'tcx:'a,R>(relation: &mut R, where R: TypeRelation<'a,'tcx> { let mut substs = Substs::empty(); + let mut obligations = Vec::new(); for &space in &ParamSpace::all() { let a_tps = a_subst.types.get_slice(space); let b_tps = b_subst.types.get_slice(space); let t_variances = variances.map(|v| v.types.get_slice(space)); - let tps = try!(relate_type_params(relation, t_variances, a_tps, b_tps)); + let RelateOk { value: tps, obligations: new_obligations } = + try!(relate_type_params(relation, t_variances, a_tps, b_tps)); + obligations.extend(new_obligations); substs.types.replace(space, tps); } @@ -166,16 +260,18 @@ fn relate_substs<'a,'tcx:'a,R>(relation: &mut R, let a_regions = a.get_slice(space); let b_regions = b.get_slice(space); let r_variances = variances.map(|v| v.regions.get_slice(space)); - let regions = try!(relate_region_params(relation, - r_variances, - a_regions, - b_regions)); + let RelateOk { value: regions, obligations: new_obligations } = + try!(relate_region_params(relation, + r_variances, + a_regions, + b_regions)); + obligations.extend(new_obligations); substs.mut_regions().replace(space, regions); } } } - Ok(substs) + Ok(RelateOk { value: substs, obligations: obligations }) } fn relate_type_params<'a,'tcx:'a,R>(relation: &mut R, @@ -191,14 +287,13 @@ fn relate_type_params<'a,'tcx:'a,R>(relation: &mut R, &b_tys.len()))); } - (0 .. a_tys.len()) + relate_result_from_iter((0 .. a_tys.len()) .map(|i| { let a_ty = a_tys[i]; let b_ty = b_tys[i]; let v = variances.map_or(ty::Invariant, |v| v[i]); relation.relate_with_variance(v, &a_ty, &b_ty) - }) - .collect() + })) } fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R, @@ -222,14 +317,13 @@ fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R, assert_eq!(num_region_params, b_rs.len()); - (0..a_rs.len()) + relate_result_from_iter((0..a_rs.len()) .map(|i| { let a_r = a_rs[i]; let b_r = b_rs[i]; let variance = variances.map_or(ty::Invariant, |v| v[i]); relation.relate_with_variance(variance, &a_r, &b_r) - }) - .collect() + })) } impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BareFnTy<'tcx> { @@ -242,9 +336,12 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BareFnTy<'tcx> { let unsafety = try!(relation.relate(&a.unsafety, &b.unsafety)); let abi = try!(relation.relate(&a.abi, &b.abi)); let sig = try!(relation.relate(&a.sig, &b.sig)); - Ok(ty::BareFnTy {unsafety: unsafety, - abi: abi, - sig: sig}) + let RelateOk { value: ((unsafety, abi), sig), obligations } = + unsafety.chain(abi).chain(sig); + Ok(RelateOk { + value: ty::BareFnTy {unsafety: unsafety, abi: abi, sig: sig}, + obligations: obligations, + }) } } @@ -266,17 +363,19 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { let output = try!(match (a.output, b.output) { (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) => - Ok(ty::FnConverging(try!(relation.relate(&a_ty, &b_ty)))), + relation.relate(&a_ty, &b_ty).map_value(|x| ty::FnConverging(x)), (ty::FnDiverging, ty::FnDiverging) => - Ok(ty::FnDiverging), + Ok(RelateOk::from(ty::FnDiverging)), (a, b) => Err(TypeError::ConvergenceMismatch( expected_found(relation, &(a != ty::FnDiverging), &(b != ty::FnDiverging)))), }); - return Ok(ty::FnSig {inputs: inputs, - output: output, - variadic: a.variadic}); + let RelateOk { value: (inputs, output), obligations } = inputs.chain(output); + Ok(RelateOk { + value: ty::FnSig {inputs: inputs, output: output, variadic: a.variadic}, + obligations: obligations + }) } } @@ -290,9 +389,8 @@ fn relate_arg_vecs<'a,'tcx:'a,R>(relation: &mut R, return Err(TypeError::ArgCount); } - a_args.iter().zip(b_args) - .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b)) - .collect() + relate_result_from_iter(a_args.iter().zip(b_args) + .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b))) } impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety { @@ -305,7 +403,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety { if a != b { Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) } else { - Ok(*a) + Ok(RelateOk::from(*a)) } } } @@ -318,7 +416,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for abi::Abi { where R: TypeRelation<'a,'tcx> { if a == b { - Ok(*a) + Ok(RelateOk::from(*a)) } else { Err(TypeError::AbiMismatch(expected_found(relation, a, b))) } @@ -336,8 +434,9 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionTy<'tcx> { Err(TypeError::ProjectionNameMismatched( expected_found(relation, &a.item_name, &b.item_name))) } else { - let trait_ref = try!(relation.relate(&a.trait_ref, &b.trait_ref)); - Ok(ty::ProjectionTy { trait_ref: trait_ref, item_name: a.item_name }) + relation.relate(&a.trait_ref, &b.trait_ref).map_value(|trait_ref| { + ty::ProjectionTy { trait_ref: trait_ref, item_name: a.item_name } + }) } } } @@ -349,9 +448,13 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionPredicate<'tcx> { -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> where R: TypeRelation<'a,'tcx> { - let projection_ty = try!(relation.relate(&a.projection_ty, &b.projection_ty)); - let ty = try!(relation.relate(&a.ty, &b.ty)); - Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) + let RelateOk { value: (projection_ty, ty), obligations } = + try!(relation.relate(&a.projection_ty, &b.projection_ty)) + .chain(try!(relation.relate(&a.ty, &b.ty))); + Ok(RelateOk { + value: ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }, + obligations: obligations, + }) } } @@ -370,9 +473,8 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec> { if a.len() != b.len() { Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len()))) } else { - a.iter().zip(b) - .map(|(a, b)| relation.relate(a, b)) - .collect() + relate_result_from_iter(a.iter().zip(b) + .map(|(a, b)| relation.relate(a, b))) } } } @@ -392,9 +494,15 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> { &b.region_bound))); let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds)); let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds)); - Ok(ty::ExistentialBounds { region_bound: r, - builtin_bounds: nb, - projection_bounds: pb }) + let RelateOk { value: ((r, nb), pb), obligations } = r.chain(nb).chain(pb); + Ok(RelateOk { + value: ty::ExistentialBounds { + region_bound: r, + builtin_bounds: nb, + projection_bounds: pb + }, + obligations: obligations, + }) } } @@ -410,7 +518,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BuiltinBounds { if a != b { Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b))) } else { - Ok(*a) + Ok(RelateOk::from(*a)) } } } @@ -426,8 +534,10 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TraitRef<'tcx> { if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = try!(relate_item_substs(relation, a.def_id, a.substs, b.substs)); - Ok(ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) }) + relate_item_substs(relation, a.def_id, a.substs, b.substs) + .map_value(|substs| { + ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) } + }) } } } @@ -466,7 +576,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TyError, _) | (_, &ty::TyError) => { - Ok(tcx.types.err) + Ok(RelateOk::from(tcx.types.err)) } (&ty::TyChar, _) | @@ -477,34 +587,37 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TyStr, _) if a == b => { - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyParam(ref a_p), &ty::TyParam(ref b_p)) if a_p.idx == b_p.idx && a_p.space == b_p.space => { - Ok(a) + Ok(RelateOk::from(a)) } (&ty::TyEnum(a_def, a_substs), &ty::TyEnum(b_def, b_substs)) if a_def == b_def => { - let substs = try!(relate_item_substs(relation, a_def.did, a_substs, b_substs)); - Ok(tcx.mk_enum(a_def, tcx.mk_substs(substs))) + relate_item_substs(relation, a_def.did, a_substs, b_substs).map_value(|substs| { + tcx.mk_enum(a_def, tcx.mk_substs(substs)) + }) } (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) => { - let principal = try!(relation.relate(&a_.principal, &b_.principal)); - let bounds = try!(relation.relate(&a_.bounds, &b_.bounds)); - Ok(tcx.mk_trait(principal, bounds)) + let RelateOk { value: (principal, bounds), obligations } = + try!(relation.relate(&a_.principal, &b_.principal)) + .chain(try!(relation.relate(&a_.bounds, &b_.bounds))); + Ok(RelateOk { value: tcx.mk_trait(principal, bounds), obligations: obligations }) } (&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs)) if a_def == b_def => { - let substs = try!(relate_item_substs(relation, a_def.did, a_substs, b_substs)); - Ok(tcx.mk_struct(a_def, tcx.mk_substs(substs))) + relate_item_substs(relation, a_def.did, a_substs, b_substs).map_value(|substs| { + tcx.mk_struct(a_def, tcx.mk_substs(substs)) + }) } (&ty::TyClosure(a_id, ref a_substs), @@ -514,34 +627,34 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, // All TyClosure types with the same id represent // the (anonymous) type of the same closure expression. So // all of their regions should be equated. - let substs = try!(relation.relate(a_substs, b_substs)); - Ok(tcx.mk_closure_from_closure_substs(a_id, substs)) + relation.relate(a_substs, b_substs).map_value(|substs| { + tcx.mk_closure_from_closure_substs(a_id, substs) + }) } (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) => { - let typ = try!(relation.relate(&a_inner, &b_inner)); - Ok(tcx.mk_box(typ)) + relation.relate(&a_inner, &b_inner).map_value(|typ| tcx.mk_box(typ)) } (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) => { - let mt = try!(relation.relate(a_mt, b_mt)); - Ok(tcx.mk_ptr(mt)) + relation.relate(a_mt, b_mt).map_value(|mt| tcx.mk_ptr(mt)) } (&ty::TyRef(a_r, ref a_mt), &ty::TyRef(b_r, ref b_mt)) => { - let r = try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r)); - let mt = try!(relation.relate(a_mt, b_mt)); - Ok(tcx.mk_ref(tcx.mk_region(r), mt)) + let RelateOk { value: (r, mt), obligations } = + try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r)) + .chain(try!(relation.relate(a_mt, b_mt))); + Ok(RelateOk { value: tcx.mk_ref(tcx.mk_region(r), mt), obligations: obligations }) } (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) => { - let t = try!(relation.relate(&a_t, &b_t)); + let RelateOk { value: t, obligations } = try!(relation.relate(&a_t, &b_t)); if sz_a == sz_b { - Ok(tcx.mk_array(t, sz_a)) + Ok(RelateOk { value: tcx.mk_array(t, sz_a), obligations: obligations }) } else { Err(TypeError::FixedArraySize(expected_found(relation, &sz_a, &sz_b))) } @@ -549,17 +662,15 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TySlice(a_t), &ty::TySlice(b_t)) => { - let t = try!(relation.relate(&a_t, &b_t)); - Ok(tcx.mk_slice(t)) + relation.relate(&a_t, &b_t).map_value(|t| tcx.mk_slice(t)) } (&ty::TyTuple(ref as_), &ty::TyTuple(ref bs)) => { if as_.len() == bs.len() { - let ts = try!(as_.iter().zip(bs) - .map(|(a, b)| relation.relate(a, b)) - .collect::>()); - Ok(tcx.mk_tup(ts)) + relate_result_from_iter( + as_.iter().zip(bs).map(|(a, b)| relation.relate(a, b))) + .map_value(|ts| tcx.mk_tup(ts)) } else if !(as_.is_empty() || bs.is_empty()) { Err(TypeError::TupleSize( expected_found(relation, &as_.len(), &bs.len()))) @@ -571,14 +682,16 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TyBareFn(a_opt_def_id, a_fty), &ty::TyBareFn(b_opt_def_id, b_fty)) if a_opt_def_id == b_opt_def_id => { - let fty = try!(relation.relate(a_fty, b_fty)); - Ok(tcx.mk_fn(a_opt_def_id, tcx.mk_bare_fn(fty))) + relation.relate(a_fty, b_fty).map_value(|fty| { + tcx.mk_fn(a_opt_def_id, tcx.mk_bare_fn(fty)) + }) } (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => { - let projection_ty = try!(relation.relate(a_data, b_data)); - Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) + relation.relate(a_data, b_data).map_value(|projection_ty| { + tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name) + }) } _ => @@ -595,10 +708,14 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ClosureSubsts<'tcx> { -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> where R: TypeRelation<'a,'tcx> { - let func_substs = try!(relate_substs(relation, None, a.func_substs, b.func_substs)); - let upvar_tys = try!(relation.relate_zip(&a.upvar_tys, &b.upvar_tys)); - Ok(ty::ClosureSubsts { func_substs: relation.tcx().mk_substs(func_substs), - upvar_tys: upvar_tys }) + let RelateOk { value: (func_substs, upvar_tys), obligations } = + try!(relate_substs(relation, None, a.func_substs, b.func_substs)) + .chain(try!(relation.relate_zip(&a.upvar_tys, &b.upvar_tys))); + Ok(RelateOk { + value: ty::ClosureSubsts { func_substs: relation.tcx().mk_substs(func_substs), + upvar_tys: upvar_tys }, + obligations: obligations, + }) } } @@ -637,7 +754,7 @@ impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Rc { let a: &T = a; let b: &T = b; - Ok(Rc::new(try!(relation.relate(a, b)))) + relation.relate(a, b).map_value(|v| Rc::new(v)) } } @@ -652,7 +769,7 @@ impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Box { let a: &T = a; let b: &T = b; - Ok(Box::new(try!(relation.relate(a, b)))) + relation.relate(a, b).map_value(|v| Box::new(v)) } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 3220295d9b88a..f0de54aff40c5 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -392,7 +392,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) { match self.lub().relate(&t1, &t2) { Ok(t) => { - self.assert_eq(t, t_lub); + self.assert_eq(t.value, t_lub); } Err(ref e) => { panic!("unexpected error in LUB: {}", e) @@ -408,11 +408,11 @@ impl<'a, 'tcx> Env<'a, 'tcx> { panic!("unexpected error computing LUB: {:?}", e) } Ok(t) => { - self.assert_eq(t, t_glb); + self.assert_eq(t.value, t_glb); // sanity check for good measure: - self.assert_subtype(t, t1); - self.assert_subtype(t, t2); + self.assert_subtype(t.value, t1); + self.assert_subtype(t.value, t2); } } } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 6ca48f2d8d484..7eabfdc7e0f58 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -538,13 +538,7 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, ), }; - infer::common_supertype( - fcx.infcx(), - origin, - true, - expected, - found, - ) + fcx.common_supertype(origin, true, expected, found) } }); diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 8f64e85de4b0f..334c52c8bfe39 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -71,7 +71,7 @@ use middle::ty::adjustment::{AdjustUnsafeFnPointer}; use middle::ty::{self, LvaluePreference, TypeAndMut, Ty}; use middle::ty::fold::TypeFoldable; use middle::ty::error::TypeError; -use middle::ty::relate::RelateResult; +use middle::ty::relate::{RelateOk}; use util::common::indent; use std::cell::RefCell; @@ -84,7 +84,7 @@ struct Coerce<'a, 'tcx: 'a> { unsizing_obligations: RefCell>>, } -type CoerceResult<'tcx> = RelateResult<'tcx, Option>>; +type CoerceResult<'tcx> = Result>, TypeError<'tcx>>; impl<'f, 'tcx> Coerce<'f, 'tcx> { fn tcx(&self) -> &ty::ctxt<'tcx> { @@ -92,8 +92,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> { - try!(self.fcx.infcx().sub_types(false, self.origin.clone(), a, b)); - Ok(None) // No coercion required. + self.fcx.infcx().sub_types(false, self.origin.clone(), a, b) + .map(|RelateOk { obligations, .. }| { + for obligation in obligations { + self.fcx.register_predicate(obligation); + } + None + }) } fn unpack_actual_value(&self, a: Ty<'tcx>, f: F) -> T where @@ -206,13 +211,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { } let ty = self.tcx().mk_ref(r_borrow, TypeAndMut {ty: inner_ty, mutbl: mutbl_b}); - if let Err(err) = self.subtype(ty, b) { - if first_error.is_none() { - first_error = Some(err); + match self.subtype(ty, b) { + Err(err) => { + if first_error.is_none() { + first_error = Some(err); + } + None + }, + Ok(_) => { + Some(()) } - None - } else { - Some(()) } }); @@ -437,7 +445,7 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &hir::Expr, a: Ty<'tcx>, b: Ty<'tcx>) - -> RelateResult<'tcx, ()> { + -> Result<(), TypeError<'tcx>> { debug!("mk_assignty({:?} -> {:?})", a, b); let mut unsizing_obligations = vec![]; let adjustment = try!(indent(|| { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index d674fa145dc9a..1369e70d62fb3 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -12,6 +12,7 @@ use middle::free_region::FreeRegionMap; use middle::infer::{self, TypeOrigin}; use middle::traits; use middle::ty::{self}; +use middle::ty::relate::RelateOk; use middle::subst::{self, Subst, Substs, VecPerParamSpace}; use syntax::ast; @@ -323,13 +324,20 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method: trait_fty={:?}", trait_fty); - try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty)); + let RelateOk { obligations, .. } = + try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty)); + for obligation in obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } infcx.leak_check(&skol_map, snapshot) }); match err { - Ok(()) => { } + Ok(RelateOk { obligations, .. }) => + for obligation in obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + }, Err(terr) => { debug!("checking trait method for compatibility: impl ty {:?}, trait ty {:?}", impl_fty, @@ -475,7 +483,10 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>, }); match err { - Ok(()) => { } + Ok(RelateOk { obligations, .. }) => + for obligation in obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + }, Err(terr) => { debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}", impl_ty, diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 63dac49b384a7..922801f32466a 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -11,7 +11,7 @@ use check::{coercion, FnCtxt}; use middle::ty::{self, Ty}; -use middle::infer::{self, TypeOrigin}; +use middle::infer::{TypeOrigin}; use std::result::Result::{Err, Ok}; use syntax::codemap::Span; @@ -35,8 +35,8 @@ pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, F: FnOnce(Span, Ty<'tcx>, Ty<'tcx>, &ty::error::TypeError<'tcx>), { // n.b.: order of actual, expected is reversed - match infer::mk_subty(fcx.infcx(), b_is_expected, TypeOrigin::Misc(sp), - ty_b, ty_a) { + match fcx.mk_subty(b_is_expected, TypeOrigin::Misc(sp), + ty_b, ty_a) { Ok(()) => { /* ok */ } Err(ref err) => { handle_err(sp, ty_a, ty_b, err); @@ -46,7 +46,7 @@ pub fn suptype_with_fn<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { - match infer::mk_eqty(fcx.infcx(), false, TypeOrigin::Misc(sp), actual, expected) { + match fcx.mk_eqty(false, TypeOrigin::Misc(sp), actual, expected) { Ok(()) => { /* ok */ } Err(ref err) => { fcx.report_mismatched_types(sp, expected, actual, err); } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 3cf182a0d8ff6..1f9473908f601 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -20,8 +20,9 @@ use middle::subst; use middle::subst::Subst; use middle::traits; use middle::ty::{self, NoPreference, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; -use middle::infer; +use middle::ty::error::{TypeError}; use middle::infer::{InferCtxt, TypeOrigin}; +use middle::ty::relate::RelateOk; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; use rustc_front::hir; @@ -1133,8 +1134,14 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { /////////////////////////////////////////////////////////////////////////// // MISCELLANY - fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> { + fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> Result<(), TypeError<'tcx>> { self.infcx().sub_types(false, TypeOrigin::Misc(DUMMY_SP), sub, sup) + .map(|RelateOk { value, obligations }| { + for obligation in obligations { + self.fcx.register_predicate(obligation); + } + value + }) } fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f890e087573b5..4ccfdae5301f0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -102,6 +102,7 @@ use middle::ty::{MethodCall, MethodCallee}; use middle::ty::adjustment; use middle::ty::error::TypeError; use middle::ty::fold::{TypeFolder, TypeFoldable}; +use middle::ty::relate::RelateOk; use middle::ty::util::Representability; use require_c_abi_if_variadic; use rscope::{ElisionFailureInfo, RegionScope}; @@ -1206,6 +1207,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self.inh.infcx } + pub fn fulfillment_cx(&self) -> &RefCell> { + &self.inh.fulfillment_cx + } + pub fn param_env(&self) -> &ty::ParameterEnvironment<'a,'tcx> { &self.inh.infcx.parameter_environment } @@ -1248,6 +1253,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty } + pub fn common_supertype(&self, + origin: TypeOrigin, + a_is_expected: bool, + a: Ty<'tcx>, + b: Ty<'tcx>) + -> Ty<'tcx> + { + let RelateOk { value, obligations } = infer::common_supertype( + self.infcx(), origin, a_is_expected, a, b); + for obligation in obligations { + self.register_predicate(obligation); + } + value + } + fn record_deferred_call_resolution(&self, closure_def_id: DefId, r: DeferredCallResolutionHandler<'tcx>) { @@ -1593,6 +1613,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sup: Ty<'tcx>) -> Result<(), TypeError<'tcx>> { infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup) + .map(|RelateOk { value, obligations }| { + for obligation in obligations { + self.register_predicate(obligation); + } + value + }) } pub fn mk_eqty(&self, @@ -1602,6 +1628,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sup: Ty<'tcx>) -> Result<(), TypeError<'tcx>> { infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup) + .map(|RelateOk { value, obligations }| { + for obligation in obligations { + self.register_predicate(obligation); + } + value + }) } pub fn mk_subr(&self, @@ -1885,9 +1917,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Neither => { if let Some(default) = default_map.get(ty) { let default = default.clone(); - match infer::mk_eqty(self.infcx(), false, - TypeOrigin::Misc(default.origin_span), - ty, default.ty) { + match self.mk_eqty(false, + TypeOrigin::Misc(default.origin_span), + ty, default.ty) { Ok(()) => {} Err(_) => { conflicts.push((*ty, default)); @@ -1978,9 +2010,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Neither => { if let Some(default) = default_map.get(ty) { let default = default.clone(); - match infer::mk_eqty(self.infcx(), false, - TypeOrigin::Misc(default.origin_span), - ty, default.ty) { + match self.mk_eqty(false, + TypeOrigin::Misc(default.origin_span), + ty, default.ty) { Ok(()) => {} Err(_) => { result = Some(default); @@ -2880,18 +2912,16 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, Some(ref else_expr) => { check_expr_with_expectation(fcx, &else_expr, expected); let else_ty = fcx.expr_ty(&else_expr); - infer::common_supertype(fcx.infcx(), - TypeOrigin::IfExpression(sp), - true, - then_ty, - else_ty) + fcx.common_supertype(TypeOrigin::IfExpression(sp), + true, + then_ty, + else_ty) } None => { - infer::common_supertype(fcx.infcx(), - TypeOrigin::IfExpressionWithNoElse(sp), - false, - then_ty, - fcx.tcx().mk_nil()) + fcx.common_supertype(TypeOrigin::IfExpressionWithNoElse(sp), + false, + then_ty, + fcx.tcx().mk_nil()) } }; @@ -3685,11 +3715,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, Some(fcx.tcx().types.err) } (Some(t_start), Some(t_end)) => { - Some(infer::common_supertype(fcx.infcx(), - TypeOrigin::RangeExpression(expr.span), - true, - t_start, - t_end)) + Some(fcx.common_supertype(TypeOrigin::RangeExpression(expr.span), + true, + t_start, + t_end)) } _ => None }; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 2335b76626b17..f71841dc358f8 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -92,6 +92,7 @@ use middle::region::{self, CodeExtent}; use middle::subst::Substs; use middle::traits; use middle::ty::{self, Ty, MethodCall, TypeFoldable}; +use middle::ty::relate::RelateOk; use middle::infer::{self, GenericKind, InferCtxt, SubregionOrigin, TypeOrigin, VerifyBound}; use middle::pat_util; use middle::ty::adjustment; @@ -1846,7 +1847,12 @@ fn declared_projection_bounds_from_trait<'a,'tcx>(rcx: &Rcx<'a, 'tcx>, // check whether this predicate applies to our current projection match infer::mk_eqty(infcx, false, TypeOrigin::Misc(span), ty, outlives.0) { - Ok(()) => { Ok(outlives.1) } + Ok(RelateOk { obligations, .. }) => { + for obligation in obligations { + fcx.register_predicate(obligation); + } + Ok(outlives.1) + } Err(_) => { Err(()) } } });