diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs index a9ea395e6b3cd..64daea32432de 100644 --- a/src/librustc/infer/bivariate.rs +++ b/src/librustc/infer/bivariate.rs @@ -28,6 +28,7 @@ use super::combine::{self, CombineFields}; use super::type_variable::{BiTo}; +use traits::PredicateObligations; use ty::{self, Ty, TyCtxt}; use ty::TyVar; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -42,7 +43,7 @@ impl<'a, 'tcx> Bivariate<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, PredicateObligations<'tcx>> for Bivariate<'a, 'tcx> { fn tag(&self) -> &'static str { "Bivariate" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.tcx() } @@ -52,7 +53,8 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { fn relate_with_variance>(&mut self, variance: ty::Variance, a: &T, - b: &T) + b: &T, + side_effects: &mut PredicateObligations<'tcx>) -> RelateResult<'tcx, T> { match variance { @@ -63,15 +65,17 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { // Foo <: Foo // // then still A must equal B. - ty::Invariant => self.relate(a, b), + ty::Invariant => self.relate(a, b, side_effects), - ty::Covariant => self.relate(a, b), - ty::Bivariant => self.relate(a, b), - ty::Contravariant => self.relate(a, b), + ty::Covariant => self.relate(a, b, side_effects), + ty::Bivariant => self.relate(a, b, side_effects), + ty::Contravariant => self.relate(a, b, side_effects), } } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } @@ -86,32 +90,35 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> { } (&ty::TyInfer(TyVar(a_id)), _) => { - self.fields.instantiate(b, BiTo, a_id)?; + self.fields.instantiate(b, BiTo, a_id, side_effects)?; Ok(a) } (_, &ty::TyInfer(TyVar(b_id))) => { - self.fields.instantiate(a, BiTo, b_id)?; + self.fields.instantiate(a, BiTo, b_id, side_effects)?; Ok(a) } _ => { - combine::super_combine_tys(self.fields.infcx, self, a, b) + combine::super_combine_tys(self.fields.infcx, self, a, b, side_effects) } } } - fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, _: ty::Region, _: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Region> + { Ok(a) } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - where T: Relate<'a,'tcx> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a, 'tcx> { let a1 = self.tcx().erase_late_bound_regions(a); let b1 = self.tcx().erase_late_bound_regions(b); - let c = self.relate(&a1, &b1)?; + let c = self.relate(&a1, &b1, side_effects)?; Ok(ty::Binder(c)) } } diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 2b30698882d62..9e59ed3ffeccb 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -41,6 +41,7 @@ use super::{InferCtxt}; use super::{MiscVariable, TypeTrace}; use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf}; +use traits::PredicateObligations; use ty::{IntType, UintType}; use ty::{self, Ty, TyCtxt}; use ty::error::TypeError; @@ -58,12 +59,13 @@ pub struct CombineFields<'a, 'tcx: 'a> { pub cause: Option, } -pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>, - relation: &mut R, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where R: TypeRelation<'a,'tcx> +pub fn super_combine_tys<'a, 'tcx, R>(infcx: &InferCtxt<'a, 'tcx>, + relation: &mut R, + a: Ty<'tcx>, + b: Ty<'tcx>, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a, 'tcx, PredicateObligations<'tcx>>, 'tcx: 'a { let a_is_expected = relation.a_is_expected(); @@ -112,7 +114,7 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>, _ => { - ty::relate::super_relate_tys(relation, a, b) + ty::relate::super_relate_tys(relation, a, b, side_effects) } } } @@ -181,7 +183,8 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn instantiate(&self, a_ty: Ty<'tcx>, dir: RelationDir, - b_vid: ty::TyVid) + b_vid: ty::TyVid, + side_effects: &mut PredicateObligations<'tcx>) -> RelateResult<'tcx, ()> { let mut stack = Vec::new(); @@ -251,10 +254,11 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> { // to associate causes/spans with each of the relations in // the stack to get this right. 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), + BiTo => self.bivariate().relate(&a_ty, &b_ty, side_effects), + EqTo => self.equate().relate(&a_ty, &b_ty, side_effects), + SubtypeOf => self.sub().relate(&a_ty, &b_ty, side_effects), + SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty, + side_effects), }?; } diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 3c9c9c5788414..0702d88ceb499 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -13,6 +13,7 @@ use super::higher_ranked::HigherRankedRelations; use super::{Subtype}; use super::type_variable::{EqTo}; +use traits::PredicateObligations; use ty::{self, Ty, TyCtxt}; use ty::TyVar; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -28,23 +29,26 @@ impl<'a, 'tcx> Equate<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, PredicateObligations<'tcx>> for Equate<'a, 'tcx> { fn tag(&self) -> &'static str { "Equate" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn relate_with_variance>(&mut self, - _: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, T> { - self.relate(a, b) + self.relate(a, b, side_effects) } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } @@ -59,23 +63,25 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { } (&ty::TyInfer(TyVar(a_id)), _) => { - self.fields.instantiate(b, EqTo, a_id)?; + self.fields.instantiate(b, EqTo, a_id, side_effects)?; Ok(a) } (_, &ty::TyInfer(TyVar(b_id))) => { - self.fields.instantiate(a, EqTo, b_id)?; + self.fields.instantiate(a, EqTo, b_id, side_effects)?; Ok(a) } _ => { - combine::super_combine_tys(self.fields.infcx, self, a, b)?; + combine::super_combine_tys(self.fields.infcx, self, a, b, side_effects)?; Ok(a) } } } - fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region, _: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Region> + { debug!("{}.regions({:?}, {:?})", self.tag(), a, @@ -85,11 +91,12 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> { Ok(a) } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Binder> where T: Relate<'a, 'tcx> { - self.fields.higher_ranked_sub(a, b)?; - self.fields.higher_ranked_sub(b, a) + self.fields.higher_ranked_sub(a, b, side_effects)?; + self.fields.higher_ranked_sub(b, a, side_effects) } } diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs index 235428a6898a9..25f66514b5a29 100644 --- a/src/librustc/infer/glb.rs +++ b/src/librustc/infer/glb.rs @@ -14,6 +14,7 @@ use super::InferCtxt; use super::lattice::{self, LatticeDir}; use super::Subtype; +use traits::PredicateObligations; use ty::{self, Ty, TyCtxt}; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -28,7 +29,7 @@ impl<'a, 'tcx> Glb<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, PredicateObligations<'tcx>> for Glb<'a, 'tcx> { fn tag(&self) -> &'static str { "Glb" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.tcx() } @@ -38,22 +39,28 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> { fn relate_with_variance>(&mut self, variance: ty::Variance, a: &T, - b: &T) + b: &T, + side_effects: &mut PredicateObligations<'tcx>) -> RelateResult<'tcx, T> { match variance { - ty::Invariant => self.fields.equate().relate(a, b), - ty::Covariant => self.relate(a, b), - ty::Bivariant => self.fields.bivariate().relate(a, b), - ty::Contravariant => self.fields.lub().relate(a, b), + ty::Invariant => self.fields.equate().relate(a, b, side_effects), + ty::Covariant => self.relate(a, b, side_effects), + ty::Bivariant => self.fields.bivariate().relate(a, b, side_effects), + ty::Contravariant => self.fields.lub().relate(a, b, side_effects), } } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - lattice::super_lattice_tys(self, a, b) + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + { + lattice::super_lattice_tys(self, a, b, side_effects) } - fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region, + _: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Region> + { debug!("{}.regions({:?}, {:?})", self.tag(), a, @@ -63,11 +70,12 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> { Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b)) } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Binder> where T: Relate<'a, 'tcx> { - self.fields.higher_ranked_glb(a, b) + self.fields.higher_ranked_glb(a, b, side_effects) } } @@ -76,10 +84,13 @@ impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> { self.fields.infcx } - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ()> + { let mut sub = self.fields.sub(); - sub.relate(&v, &a)?; - sub.relate(&v, &b)?; + sub.relate(&v, &a, side_effects)?; + sub.relate(&v, &b, side_effects)?; Ok(()) } } diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index db4ee17bafbbd..2abeceeea09b2 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -14,6 +14,7 @@ use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SkolemizationMap}; use super::combine::CombineFields; +use traits::PredicateObligations; use ty::{self, TyCtxt, Binder, TypeFoldable}; use ty::error::TypeError; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -21,14 +22,20 @@ use syntax::codemap::Span; use util::nodemap::{FnvHashMap, FnvHashSet}; pub trait HigherRankedRelations<'a,'tcx> { - fn higher_ranked_sub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> - where T: Relate<'a,'tcx>; - - fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> - where T: Relate<'a,'tcx>; - - fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> - where T: Relate<'a,'tcx>; + fn higher_ranked_sub(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Binder> + where T: Relate<'a, 'tcx>; + + fn higher_ranked_lub(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Binder> + where T: Relate<'a, 'tcx>; + + fn higher_ranked_glb(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Binder> + where T: Relate<'a, 'tcx>; } trait InferCtxtExt { @@ -40,9 +47,10 @@ trait InferCtxtExt { } impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { - fn higher_ranked_sub(&self, a: &Binder, b: &Binder) + fn higher_ranked_sub(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) -> RelateResult<'tcx, Binder> - where T: Relate<'a,'tcx> + where T: Relate<'a, 'tcx> { debug!("higher_ranked_sub(a={:?}, b={:?})", a, b); @@ -75,7 +83,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { debug!("b_prime={:?}", b_prime); // Compare types now that bound regions have been replaced. - let result = self.sub().relate(&a_prime, &b_prime)?; + let result = self.sub().relate(&a_prime, &b_prime, side_effects)?; // Presuming type comparison succeeds, we need to check // that the skolemized regions do not "leak". @@ -101,8 +109,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { }); } - fn higher_ranked_lub(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> - where T: Relate<'a,'tcx> + fn higher_ranked_lub(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Binder> + where T: Relate<'a, 'tcx> { // Start a snapshot so we can examine "all bindings that were // created as part of this type comparison". @@ -118,7 +128,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { // Collect constraints. let result0 = - self.lub().relate(&a_with_fresh, &b_with_fresh)?; + self.lub().relate(&a_with_fresh, &b_with_fresh, side_effects)?; let result0 = self.infcx.resolve_type_vars_if_possible(&result0); debug!("lub result0 = {:?}", result0); @@ -191,7 +201,9 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { } } - fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> RelateResult<'tcx, Binder> + fn higher_ranked_glb(&self, a: &Binder, b: &Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Binder> where T: Relate<'a,'tcx> { debug!("higher_ranked_glb({:?}, {:?})", @@ -212,7 +224,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> { // Collect constraints. let result0 = - self.glb().relate(&a_with_fresh, &b_with_fresh)?; + self.glb().relate(&a_with_fresh, &b_with_fresh, side_effects)?; let result0 = self.infcx.resolve_type_vars_if_possible(&result0); debug!("glb result0 = {:?}", result0); diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs index 17ad32e742e02..ab30903c0636d 100644 --- a/src/librustc/infer/lattice.rs +++ b/src/librustc/infer/lattice.rs @@ -32,23 +32,27 @@ use super::combine; use super::InferCtxt; +use traits::PredicateObligations; use ty::TyVar; use ty::{self, Ty}; use ty::relate::{RelateResult, TypeRelation}; -pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> { +pub trait LatticeDir<'f, 'tcx>: TypeRelation<'f, 'tcx, PredicateObligations<'tcx>> { fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; // Relates the type `v` to `a` and `b` such that `v` represents // the LUB/GLB of `a` and `b` as appropriate. - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>; + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ()>; } -pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where 'tcx: 'a +pub fn super_lattice_tys<'a, 'tcx, L>(this: &mut L, + a: Ty<'tcx>, + b: Ty<'tcx>, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + where 'tcx: 'a, L: LatticeDir<'a,'tcx> { debug!("{}.lattice_tys({:?}, {:?})", this.tag(), @@ -66,19 +70,19 @@ 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(); - this.relate_bound(v, a, b)?; + this.relate_bound(v, a, b, side_effects)?; Ok(v) } (&ty::TyInfer(TyVar(..)), _) | (_, &ty::TyInfer(TyVar(..))) => { let v = infcx.next_ty_var(); - this.relate_bound(v, a, b)?; + this.relate_bound(v, a, b, side_effects)?; Ok(v) } _ => { - combine::super_combine_tys(this.infcx(), this, a, b) + combine::super_combine_tys(this.infcx(), this, a, b, side_effects) } } } diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs index 00b85929b4b15..a9b2895a72301 100644 --- a/src/librustc/infer/lub.rs +++ b/src/librustc/infer/lub.rs @@ -14,6 +14,7 @@ use super::InferCtxt; use super::lattice::{self, LatticeDir}; use super::Subtype; +use traits::PredicateObligations; use ty::{self, Ty, TyCtxt}; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -28,32 +29,37 @@ impl<'a, 'tcx> Lub<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, PredicateObligations<'tcx>> for Lub<'a, 'tcx> { fn tag(&self) -> &'static str { "Lub" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.tcx() } fn a_is_expected(&self) -> bool { self.fields.a_is_expected } - fn relate_with_variance>(&mut self, - variance: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, T> { match variance { - ty::Invariant => self.fields.equate().relate(a, b), - ty::Covariant => self.relate(a, b), - ty::Bivariant => self.fields.bivariate().relate(a, b), - ty::Contravariant => self.fields.glb().relate(a, b), + ty::Invariant => self.fields.equate().relate(a, b, side_effects), + ty::Covariant => self.relate(a, b, side_effects), + ty::Bivariant => self.fields.bivariate().relate(a, b, side_effects), + ty::Contravariant => self.fields.glb().relate(a, b, side_effects), } } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - lattice::super_lattice_tys(self, a, b) + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + { + lattice::super_lattice_tys(self, a, b, side_effects) } - fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region, _: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Region> + { debug!("{}.regions({:?}, {:?})", self.tag(), a, @@ -63,23 +69,27 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> { Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b)) } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Binder> where T: Relate<'a, 'tcx> { - self.fields.higher_ranked_lub(a, b) + self.fields.higher_ranked_lub(a, b, side_effects) } } -impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> { - fn infcx(&self) -> &'a InferCtxt<'a,'tcx> { +impl<'a, 'tcx> LatticeDir<'a, 'tcx> for Lub<'a, 'tcx> { + fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx } - fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { + fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ()> + { let mut sub = self.fields.sub(); - sub.relate(&a, &v)?; - sub.relate(&b, &v)?; + sub.relate(&a, &v, side_effects)?; + sub.relate(&b, &v, side_effects)?; Ok(()) } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index bc4c9fd2ccfcf..73c7b36c3f92d 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -24,16 +24,14 @@ use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::region::CodeExtent; -use ty::subst; -use ty::subst::Substs; -use ty::subst::Subst; -use traits::{self, ProjectionMode}; +use traits::{self, ProjectionMode, PredicateObligations}; +use ty::subst::{self, Subst, Substs}; use ty::adjustment; use ty::{TyVid, IntVid, FloatVid}; use ty::{self, Ty, TyCtxt}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::{TypeFolder, TypeFoldable}; -use ty::relate::{Relate, RelateResult, TypeRelation}; +use ty::relate::{Relate, TypeRelation}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{RefCell, Ref}; use std::fmt; @@ -63,8 +61,13 @@ pub mod sub; pub mod type_variable; pub mod unify_key; +pub struct InferOk<'tcx> { + pub obligations: PredicateObligations<'tcx>, +} +pub type InferResult<'tcx> = Result, TypeError<'tcx>>; + pub type Bound = Option; -pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" +pub type UnitResult<'tcx> = Result<(), TypeError<'tcx>>; // "unify result" pub type FixupResult = Result; // "fixup result" pub struct InferCtxt<'a, 'tcx: 'a> { @@ -386,39 +389,12 @@ pub fn normalizing_infer_ctxt<'a, 'tcx>(tcx: &'a TyCtxt<'tcx>, infcx } -/// Computes the least upper-bound of `a` and `b`. If this is not possible, reports an error and -/// returns ty::err. -pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, - origin: TypeOrigin, - a_is_expected: bool, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> Ty<'tcx> -{ - debug!("common_supertype({:?}, {:?})", - a, b); - - let trace = TypeTrace { - origin: origin, - values: Types(expected_found(a_is_expected, a, b)) - }; - - let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).relate(&a, &b)); - match result { - Ok(t) => t, - Err(ref err) => { - cx.report_and_explain_type_error(trace, err).emit(); - cx.tcx.types.err - } - } -} - pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a_is_expected: bool, origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("mk_subty({:?} <: {:?})", a, b); cx.sub_types(a_is_expected, origin, a, b) @@ -427,19 +403,22 @@ pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> { + -> InferResult<'tcx> +{ debug!("can_mk_subty({:?} <: {:?})", a, b); cx.probe(|_| { let trace = TypeTrace { origin: TypeOrigin::Misc(codemap::DUMMY_SP), values: Types(expected_found(true, a, b)) }; - cx.sub(true, trace).relate(&a, &b).map(|_| ()) + let mut obligations = PredicateObligations::new(); + cx.sub(true, trace).relate(&a, &b, &mut obligations) + .map(|_| InferOk { obligations: obligations }) }) } pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { cx.can_equate(&a, &b) } @@ -447,7 +426,8 @@ pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: SubregionOrigin<'tcx>, a: ty::Region, - b: ty::Region) { + b: ty::Region) +{ debug!("mk_subr({:?} <: {:?})", a, b); let snapshot = cx.region_vars.start_snapshot(); cx.region_vars.make_subregion(origin, a, b); @@ -459,7 +439,7 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("mk_eqty({:?} <: {:?})", a, b); cx.eq_types(a_is_expected, origin, a, b) @@ -470,7 +450,7 @@ pub fn mk_eq_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: ty::TraitRef<'tcx>, b: ty::TraitRef<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("mk_eq_trait_refs({:?} = {:?})", a, b); cx.eq_trait_refs(a_is_expected, origin, a, b) @@ -481,7 +461,7 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: ty::PolyTraitRef<'tcx>, b: ty::PolyTraitRef<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("mk_sub_poly_trait_refs({:?} <: {:?})", a, b); cx.sub_poly_trait_refs(a_is_expected, origin, a, b) @@ -492,7 +472,7 @@ pub fn mk_eq_impl_headers<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, origin: TypeOrigin, a: &ty::ImplHeader<'tcx>, b: &ty::ImplHeader<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("mk_eq_impl_header({:?} = {:?})", a, b); match (a.trait_ref, b.trait_ref) { @@ -502,10 +482,8 @@ pub fn mk_eq_impl_headers<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, } } -fn expected_found(a_is_expected: bool, - a: T, - b: T) - -> ExpectedFound +fn expected_found(a_is_expected: bool, a: T, b: T) + -> ExpectedFound { if a_is_expected { ExpectedFound {expected: a, found: b} @@ -688,39 +666,42 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> CombineFields<'a, 'tcx> { - CombineFields {infcx: self, - a_is_expected: a_is_expected, - trace: trace, - cause: None} + -> CombineFields<'a, 'tcx> + { + CombineFields { + infcx: self, + a_is_expected: a_is_expected, + trace: trace, + cause: None, + } } // public so that it can be used from the rustc_driver unit tests pub fn equate(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> equate::Equate<'a, 'tcx> + -> equate::Equate<'a, 'tcx> { - self.combine_fields(a_is_expected, trace).equate() + equate::Equate::new(self.combine_fields(a_is_expected, trace)) } // public so that it can be used from the rustc_driver unit tests pub fn sub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> sub::Sub<'a, 'tcx> + -> sub::Sub<'a, 'tcx> { - self.combine_fields(a_is_expected, trace).sub() + sub::Sub::new(self.combine_fields(a_is_expected, trace)) } // public so that it can be used from the rustc_driver unit tests pub fn lub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> lub::Lub<'a, 'tcx> + -> lub::Lub<'a, 'tcx> { - self.combine_fields(a_is_expected, trace).lub() + lub::Lub::new(self.combine_fields(a_is_expected, trace)) } // public so that it can be used from the rustc_driver unit tests pub fn glb(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>) - -> glb::Glb<'a, 'tcx> + -> glb::Glb<'a, 'tcx> { - self.combine_fields(a_is_expected, trace).glb() + glb::Glb::new(self.combine_fields(a_is_expected, trace)) } fn start_snapshot(&self) -> CombinedSnapshot { @@ -856,12 +837,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'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(|_| ()) + let mut obligations = PredicateObligations::new(); + self.sub(a_is_expected, trace).relate(&a, &b, &mut obligations) + .map(|_| InferOk { obligations: obligations }) }) } @@ -870,11 +853,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: Ty<'tcx>, b: Ty<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'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(|_| ()) + let mut obligations = PredicateObligations::new(); + self.equate(a_is_expected, trace).relate(&a, &b, &mut obligations) + .map(|_| InferOk { obligations: obligations }) }) } @@ -883,7 +868,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: ty::TraitRef<'tcx>, b: ty::TraitRef<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("eq_trait_refs({:?} <: {:?})", a, @@ -893,7 +878,9 @@ 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(|_| ()) + let mut obligations = PredicateObligations::new(); + self.equate(a_is_expected, trace).relate(&a, &b, &mut obligations) + .map(|_| InferOk { obligations: obligations }) }) } @@ -902,7 +889,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin, a: ty::PolyTraitRef<'tcx>, b: ty::PolyTraitRef<'tcx>) - -> UnitResult<'tcx> + -> InferResult<'tcx> { debug!("sub_poly_trait_refs({:?} <: {:?})", a, @@ -912,7 +899,9 @@ 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(|_| ()) + let mut obligations = PredicateObligations::new(); + self.sub(a_is_expected, trace).relate(&a, &b, &mut obligations).map(|_| ()) + .map(|_| InferOk { obligations: obligations }) }) } @@ -955,20 +944,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn equality_predicate(&self, span: Span, predicate: &ty::PolyEquatePredicate<'tcx>) - -> UnitResult<'tcx> { + -> InferResult<'tcx> + { self.commit_if_ok(|snapshot| { let (ty::EquatePredicate(a, b), skol_map) = self.skolemize_late_bound_regions(predicate, snapshot); let origin = TypeOrigin::EquatePredicate(span); - let () = mk_eqty(self, false, origin, a, b)?; + let InferOk { obligations, .. } = try!(mk_eqty(self, false, origin, a, b)); self.leak_check(&skol_map, snapshot) + .map(|_| InferOk { obligations: obligations }) }) } pub fn region_outlives_predicate(&self, span: Span, predicate: &ty::PolyRegionOutlivesPredicate) - -> UnitResult<'tcx> { + -> UnitResult<'tcx> + { self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), skol_map) = self.skolemize_late_bound_regions(predicate, snapshot); @@ -1447,7 +1439,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.region_vars.verify_generic_bound(origin, kind, a, bound); } - pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx> + pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> InferResult<'tcx> where T: Relate<'b,'tcx> + fmt::Debug { debug!("can_equate({:?}, {:?})", a, b); @@ -1461,8 +1453,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { origin: TypeOrigin::Misc(codemap::DUMMY_SP), values: Types(expected_found(true, e, e)) }; - self.equate(true, trace).relate(a, b) - }).map(|_| ()) + let mut obligations = PredicateObligations::new(); + self.equate(true, trace).relate(a, b, &mut obligations) + .map(|_| InferOk { obligations: obligations }) + }) } pub fn node_ty(&self, id: ast::NodeId) -> McResult> { diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 0505c9d627b9b..870e2ff62915c 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -13,6 +13,7 @@ use super::higher_ranked::HigherRankedRelations; use super::SubregionOrigin; use super::type_variable::{SubtypeOf, SupertypeOf}; +use traits::PredicateObligations; use ty::{self, Ty, TyCtxt}; use ty::TyVar; use ty::relate::{Cause, Relate, RelateResult, TypeRelation}; @@ -29,7 +30,7 @@ impl<'a, 'tcx> Sub<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, PredicateObligations<'tcx>> for Sub<'a, 'tcx> { fn tag(&self) -> &'static str { "Sub" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.fields.infcx.tcx } fn a_is_expected(&self) -> bool { self.fields.a_is_expected } @@ -45,21 +46,24 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { r } - fn relate_with_variance>(&mut self, - variance: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, T> { match variance { - ty::Invariant => self.fields.equate().relate(a, b), - ty::Covariant => self.relate(a, b), - ty::Bivariant => self.fields.bivariate().relate(a, b), - ty::Contravariant => self.fields.switch_expected().sub().relate(b, a), + ty::Invariant => self.fields.equate().relate(a, b, side_effects), + ty::Covariant => self.relate(a, b, side_effects), + ty::Bivariant => self.fields.bivariate().relate(a, b, side_effects), + ty::Contravariant => self.fields.switch_expected().sub().relate(b, a, side_effects), } } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, Ty<'tcx>> + { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } @@ -77,11 +81,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { (&ty::TyInfer(TyVar(a_id)), _) => { self.fields .switch_expected() - .instantiate(b, SupertypeOf, a_id)?; + .instantiate(b, SupertypeOf, a_id, side_effects)?; Ok(a) } (_, &ty::TyInfer(TyVar(b_id))) => { - self.fields.instantiate(a, SubtypeOf, b_id)?; + self.fields.instantiate(a, SubtypeOf, b_id, side_effects)?; Ok(a) } @@ -90,13 +94,15 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { } _ => { - combine::super_combine_tys(self.fields.infcx, self, a, b)?; + combine::super_combine_tys(self.fields.infcx, self, a, b, side_effects)?; Ok(a) } } } - fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region, _: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Region> + { debug!("{}.regions({:?}, {:?}) self.cause={:?}", self.tag(), a, b, self.fields.cause); // FIXME -- we have more fine-grained information available @@ -107,10 +113,11 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> { Ok(a) } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut PredicateObligations<'tcx>) + -> RelateResult<'tcx, ty::Binder> where T: Relate<'a,'tcx> { - self.fields.higher_ranked_sub(a, b) + self.fields.higher_ranked_sub(a, b, side_effects) } } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 321144126c9f8..973f6cd306dfe 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -9,7 +9,7 @@ // except according to those terms. use dep_graph::DepGraph; -use infer::InferCtxt; +use infer::{InferCtxt, InferOk}; use ty::{self, Ty, TyCtxt, TypeFoldable, ToPolyTraitRef}; use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error}; use std::iter; @@ -526,7 +526,11 @@ 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(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + Ok(Some(Vec::new())) + }, Err(_) => Err(CodeSelectionError(Unimplemented)), } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 3adaf5fa6bb2f..2365fa8bc054a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -24,7 +24,7 @@ use super::VtableImplData; use super::util; use middle::def_id::DefId; -use infer::{self, TypeOrigin}; +use infer::{self, InferOk, TypeOrigin}; use ty::subst::Subst; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder}; @@ -232,7 +232,11 @@ 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(InferOk { obligations: inferred_obligations }) => { + // FIXME propagate inferred obligations + assert!(inferred_obligations.is_empty()); + Ok(Some(obligations)) + }, Err(err) => Err(MismatchedProjectionTypes { err: err }), } } @@ -278,7 +282,10 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext 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(()) => { } + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(_) => { /* ignore errors */ } } } @@ -1082,7 +1089,10 @@ fn confirm_param_env_candidate<'cx,'tcx>( origin, obligation.predicate.trait_ref.clone(), projection.projection_ty.trait_ref.clone()) { - Ok(()) => { } + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(e) => { selcx.tcx().sess.span_bug( obligation.cause.span, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e2a48688d4bbc..3ab74d09932aa 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -37,8 +37,7 @@ use super::object_safety; use super::util; use middle::def_id::DefId; -use infer; -use infer::{InferCtxt, TypeFreshener, TypeOrigin}; +use infer::{self, InferCtxt, InferOk, TypeFreshener, TypeOrigin}; use ty::subst::{Subst, Substs, TypeSpace}; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use traits; @@ -484,7 +483,11 @@ 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, + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + EvaluatedToOk + }, Err(_) => EvaluatedToErr } } @@ -1185,7 +1188,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { origin, trait_bound.clone(), ty::Binder(skol_trait_ref.clone())) { - Ok(()) => { } + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(_) => { return false; } } @@ -2498,7 +2504,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { origin, expected_trait_ref.clone(), obligation_trait_ref.clone()) { - Ok(()) => Ok(()), + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + Ok(()) + }, Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)) } } @@ -2814,8 +2824,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.sub_poly_trait_refs(false, origin, poly_trait_ref, - obligation.predicate.to_poly_trait_ref()) { - Ok(()) => Ok(()), + obligation.predicate.to_poly_trait_ref()) + { + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + Ok(()) + }, Err(_) => Err(()), } } @@ -2829,7 +2844,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> bool { let mut matcher = ty::_match::Match::new(self.tcx()); - matcher.relate(previous, current).is_ok() + matcher.relate(previous, current, &mut ()).is_ok() } fn push_stack<'o,'s:'o>(&mut self, diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index d0ccc3e0fdd80..1f42216fe6b25 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -38,21 +38,24 @@ impl<'a, 'tcx> Match<'a, 'tcx> { } } -impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { +impl<'a, 'tcx> TypeRelation<'a, 'tcx, ()> for Match<'a, 'tcx> { fn tag(&self) -> &'static str { "Match" } fn tcx(&self) -> &'a TyCtxt<'tcx> { self.tcx } fn a_is_expected(&self) -> bool { true } // irrelevant - fn relate_with_variance>(&mut self, - _: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T> + fn relate_with_variance>(&mut self, + _: ty::Variance, + a: &T, + b: &T, + side_effects: &mut ()) + -> RelateResult<'tcx, T> { - self.relate(a, b) + self.relate(a, b, side_effects) } - fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> { + fn regions(&mut self, a: ty::Region, b: ty::Region, _: &mut ()) + -> RelateResult<'tcx, ty::Region> + { debug!("{}.regions({:?}, {:?})", self.tag(), a, @@ -60,7 +63,9 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { Ok(a) } - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut ()) + -> RelateResult<'tcx, Ty<'tcx>> + { debug!("{}.tys({:?}, {:?})", self.tag(), a, b); if a == b { return Ok(a); } @@ -82,15 +87,16 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> { } _ => { - relate::super_relate_tys(self, a, b) + relate::super_relate_tys(self, a, b, side_effects) } } } - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - where T: Relate<'a,'tcx> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut ()) + -> RelateResult<'tcx, ty::Binder> + where T: Relate<'a, 'tcx> { - Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder())?)) + Ok(ty::Binder(self.relate(a.skip_binder(), b.skip_binder(), side_effects)?)) } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index bb4f13b13c1ec..93e21e8ca279c 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -28,7 +28,8 @@ pub enum Cause { ExistentialRegionBound, // relating an existential region bound } -pub trait TypeRelation<'a,'tcx> : Sized { +/// S is the type of extra side effects that may be collected during type relation. +pub trait TypeRelation<'a, 'tcx, S>: Sized { fn tcx(&self) -> &'a TyCtxt<'tcx>; /// Returns a static string we can use for printouts. @@ -45,22 +46,29 @@ pub trait TypeRelation<'a,'tcx> : Sized { } /// Generic relation routine suitable for most anything. - fn relate>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> { - Relate::relate(self, a, b) + fn relate>(&mut self, a: &T, b: &T, + side_effects: &mut S) + -> RelateResult<'tcx, T> + { + Relate::relate(self, a, b, side_effects) } /// Relete elements of two slices pairwise. - fn relate_zip>(&mut self, a: &[T], b: &[T]) -> RelateResult<'tcx, Vec> { + fn relate_zip>(&mut self, a: &[T], b: &[T], + side_effects: &mut S) + -> RelateResult<'tcx, Vec> + { assert_eq!(a.len(), b.len()); - a.iter().zip(b).map(|(a, b)| self.relate(a, b)).collect() + a.iter().zip(b).map(|(a, b)| self.relate(a, b, side_effects)).collect() } /// Switch variance for the purpose of relating `a` and `b`. - fn relate_with_variance>(&mut self, - variance: ty::Variance, - a: &T, - b: &T) - -> RelateResult<'tcx, T>; + fn relate_with_variance>(&mut self, + variance: ty::Variance, + a: &T, + b: &T, + side_effects: &mut S) + -> RelateResult<'tcx, T>; // Overrideable relations. You shouldn't typically call these // directly, instead call `relate()`, which in turn calls @@ -68,33 +76,37 @@ pub trait TypeRelation<'a,'tcx> : Sized { // additional hooks for other types in the future if needed // without making older code, which called `relate`, obsolete. - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>>; + fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, side_effects: &mut S) + -> RelateResult<'tcx, Ty<'tcx>>; - fn regions(&mut self, a: ty::Region, b: ty::Region) - -> RelateResult<'tcx, ty::Region>; + fn regions(&mut self, a: ty::Region, b: ty::Region, + side_effects: &mut S) + -> RelateResult<'tcx, ty::Region>; - fn binders(&mut self, a: &ty::Binder, b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> + fn binders(&mut self, a: &ty::Binder, b: &ty::Binder, + side_effects: &mut S) + -> RelateResult<'tcx, ty::Binder> where T: Relate<'a,'tcx>; } pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> { - fn relate>(relation: &mut R, - a: &Self, - b: &Self) - -> RelateResult<'tcx, Self>; + fn relate, S>(relation: &mut R, + a: &Self, + b: &Self, + side_effects: &mut S) + -> RelateResult<'tcx, Self>; } /////////////////////////////////////////////////////////////////////////// // Relate impls -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TypeAndMut<'tcx> { - fn relate(relation: &mut R, - a: &ty::TypeAndMut<'tcx>, - b: &ty::TypeAndMut<'tcx>) - -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::TypeAndMut<'tcx> { + fn relate(relation: &mut R, + a: &ty::TypeAndMut<'tcx>, + b: &ty::TypeAndMut<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::TypeAndMut<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { debug!("{}.mts({:?}, {:?})", relation.tag(), @@ -108,7 +120,7 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TypeAndMut<'tcx> { ast::Mutability::MutImmutable => ty::Covariant, ast::Mutability::MutMutable => ty::Invariant, }; - let ty = relation.relate_with_variance(variance, &a.ty, &b.ty)?; + let ty = relation.relate_with_variance(variance, &a.ty, &b.ty, side_effects)?; Ok(ty::TypeAndMut {ty: ty, mutbl: mutbl}) } } @@ -117,12 +129,13 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TypeAndMut<'tcx> { // substitutions are not themselves relatable without more context, // but they is an important subroutine for things that ARE relatable, // like traits etc. -fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R, - item_def_id: DefId, - a_subst: &Substs<'tcx>, - b_subst: &Substs<'tcx>) - -> RelateResult<'tcx, Substs<'tcx>> - where R: TypeRelation<'a,'tcx> +fn relate_item_substs<'a, 'tcx, R, S>(relation: &mut R, + item_def_id: DefId, + a_subst: &Substs<'tcx>, + b_subst: &Substs<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, Substs<'tcx>> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { debug!("substs: item_def_id={:?} a_subst={:?} b_subst={:?}", item_def_id, @@ -136,15 +149,16 @@ fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R, } else { None }; - relate_substs(relation, opt_variances, a_subst, b_subst) + relate_substs(relation, opt_variances, a_subst, b_subst, side_effects) } -pub fn relate_substs<'a,'tcx:'a,R>(relation: &mut R, - variances: Option<&ty::ItemVariances>, - a_subst: &Substs<'tcx>, - b_subst: &Substs<'tcx>) - -> RelateResult<'tcx, Substs<'tcx>> - where R: TypeRelation<'a,'tcx> +pub fn relate_substs<'a, 'tcx, R, S>(relation: &mut R, + variances: Option<&ty::ItemVariances>, + a_subst: &Substs<'tcx>, + b_subst: &Substs<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, Substs<'tcx>> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { let mut substs = Substs::empty(); @@ -152,7 +166,7 @@ pub fn relate_substs<'a,'tcx:'a,R>(relation: &mut R, 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 = relate_type_params(relation, t_variances, a_tps, b_tps)?; + let tps = relate_type_params(relation, t_variances, a_tps, b_tps, side_effects)?; substs.types.replace(space, tps); } @@ -163,19 +177,21 @@ pub fn relate_substs<'a,'tcx:'a,R>(relation: &mut R, let regions = relate_region_params(relation, r_variances, a_regions, - b_regions)?; + b_regions, + side_effects)?; substs.regions.replace(space, regions); } Ok(substs) } -fn relate_type_params<'a,'tcx:'a,R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_tys: &[Ty<'tcx>], - b_tys: &[Ty<'tcx>]) - -> RelateResult<'tcx, Vec>> - where R: TypeRelation<'a,'tcx> +fn relate_type_params<'a, 'tcx, R, S>(relation: &mut R, + variances: Option<&[ty::Variance]>, + a_tys: &[Ty<'tcx>], + b_tys: &[Ty<'tcx>], + side_effects: &mut S) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { if a_tys.len() != b_tys.len() { return Err(TypeError::TyParamSize(expected_found(relation, @@ -188,17 +204,18 @@ fn relate_type_params<'a,'tcx:'a,R>(relation: &mut R, 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) + relation.relate_with_variance(v, &a_ty, &b_ty, side_effects) }) .collect() } -fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R, - variances: Option<&[ty::Variance]>, - a_rs: &[ty::Region], - b_rs: &[ty::Region]) - -> RelateResult<'tcx, Vec> - where R: TypeRelation<'a,'tcx> +fn relate_region_params<'a, 'tcx, R, S>(relation: &mut R, + variances: Option<&[ty::Variance]>, + a_rs: &[ty::Region], + b_rs: &[ty::Region], + side_effects: &mut S) + -> RelateResult<'tcx, Vec> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { let num_region_params = a_rs.len(); @@ -219,33 +236,35 @@ fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R, 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) + relation.relate_with_variance(variance, &a_r, &b_r, side_effects) }) .collect() } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BareFnTy<'tcx> { - fn relate(relation: &mut R, - a: &ty::BareFnTy<'tcx>, - b: &ty::BareFnTy<'tcx>) - -> RelateResult<'tcx, ty::BareFnTy<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::BareFnTy<'tcx> { + fn relate(relation: &mut R, + a: &ty::BareFnTy<'tcx>, + b: &ty::BareFnTy<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::BareFnTy<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { - let unsafety = relation.relate(&a.unsafety, &b.unsafety)?; - let abi = relation.relate(&a.abi, &b.abi)?; - let sig = relation.relate(&a.sig, &b.sig)?; + let unsafety = relation.relate(&a.unsafety, &b.unsafety, side_effects)?; + let abi = relation.relate(&a.abi, &b.abi, side_effects)?; + let sig = relation.relate(&a.sig, &b.sig, side_effects)?; Ok(ty::BareFnTy {unsafety: unsafety, abi: abi, sig: sig}) } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { - fn relate(relation: &mut R, - a: &ty::FnSig<'tcx>, - b: &ty::FnSig<'tcx>) - -> RelateResult<'tcx, ty::FnSig<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::FnSig<'tcx> { + fn relate(relation: &mut R, + a: &ty::FnSig<'tcx>, + b: &ty::FnSig<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::FnSig<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { if a.variadic != b.variadic { return Err(TypeError::VariadicMismatch( @@ -254,11 +273,12 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { let inputs = relate_arg_vecs(relation, &a.inputs, - &b.inputs)?; + &b.inputs, + side_effects)?; let output = match (a.output, b.output) { (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) => - Ok(ty::FnConverging(relation.relate(&a_ty, &b_ty)?)), + Ok(ty::FnConverging(relation.relate(&a_ty, &b_ty, side_effects)?)), (ty::FnDiverging, ty::FnDiverging) => Ok(ty::FnDiverging), (a, b) => @@ -272,27 +292,29 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> { } } -fn relate_arg_vecs<'a,'tcx:'a,R>(relation: &mut R, - a_args: &[Ty<'tcx>], - b_args: &[Ty<'tcx>]) - -> RelateResult<'tcx, Vec>> - where R: TypeRelation<'a,'tcx> +fn relate_arg_vecs<'a, 'tcx, R, S>(relation: &mut R, + a_args: &[Ty<'tcx>], + b_args: &[Ty<'tcx>], + side_effects: &mut S) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { if a_args.len() != b_args.len() { return Err(TypeError::ArgCount); } a_args.iter().zip(b_args) - .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b)) + .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b, side_effects)) .collect() } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety { - fn relate(relation: &mut R, - a: &ast::Unsafety, - b: &ast::Unsafety) - -> RelateResult<'tcx, ast::Unsafety> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ast::Unsafety { + fn relate(relation: &mut R, + a: &ast::Unsafety, + b: &ast::Unsafety, + _: &mut S) + -> RelateResult<'tcx, ast::Unsafety> + where R: TypeRelation<'a, 'tcx, S> { if a != b { Err(TypeError::UnsafetyMismatch(expected_found(relation, a, b))) @@ -302,12 +324,13 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety { } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for abi::Abi { - fn relate(relation: &mut R, - a: &abi::Abi, - b: &abi::Abi) - -> RelateResult<'tcx, abi::Abi> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for abi::Abi { + fn relate(relation: &mut R, + a: &abi::Abi, + b: &abi::Abi, + _: &mut S) + -> RelateResult<'tcx, abi::Abi> + where R: TypeRelation<'a, 'tcx, S> { if a == b { Ok(*a) @@ -317,42 +340,45 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for abi::Abi { } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionTy<'tcx> { - fn relate(relation: &mut R, - a: &ty::ProjectionTy<'tcx>, - b: &ty::ProjectionTy<'tcx>) - -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a,'tcx: 'a> Relate<'a, 'tcx> for ty::ProjectionTy<'tcx> { + fn relate(relation: &mut R, + a: &ty::ProjectionTy<'tcx>, + b: &ty::ProjectionTy<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::ProjectionTy<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { if a.item_name != b.item_name { Err(TypeError::ProjectionNameMismatched( expected_found(relation, &a.item_name, &b.item_name))) } else { - let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref)?; + let trait_ref = relation.relate(&a.trait_ref, &b.trait_ref, side_effects)?; Ok(ty::ProjectionTy { trait_ref: trait_ref, item_name: a.item_name }) } } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionPredicate<'tcx> { - fn relate(relation: &mut R, - a: &ty::ProjectionPredicate<'tcx>, - b: &ty::ProjectionPredicate<'tcx>) - -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::ProjectionPredicate<'tcx> { + fn relate(relation: &mut R, + a: &ty::ProjectionPredicate<'tcx>, + b: &ty::ProjectionPredicate<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { - let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty)?; - let ty = relation.relate(&a.ty, &b.ty)?; + let projection_ty = relation.relate(&a.projection_ty, &b.projection_ty, side_effects)?; + let ty = relation.relate(&a.ty, &b.ty, side_effects)?; Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty }) } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec> { - fn relate(relation: &mut R, - a: &Vec>, - b: &Vec>) - -> RelateResult<'tcx, Vec>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for Vec> { + fn relate(relation: &mut R, + a: &Vec>, + b: &Vec>, + side_effects: &mut S) + -> RelateResult<'tcx, Vec>> + where R: TypeRelation<'a, 'tcx, S> { // To be compatible, `a` and `b` must be for precisely the // same set of traits and item names. We always require that @@ -363,39 +389,42 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec> { Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len()))) } else { a.iter().zip(b) - .map(|(a, b)| relation.relate(a, b)) + .map(|(a, b)| relation.relate(a, b, side_effects)) .collect() } } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> { - fn relate(relation: &mut R, - a: &ty::ExistentialBounds<'tcx>, - b: &ty::ExistentialBounds<'tcx>) - -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::ExistentialBounds<'tcx> { + fn relate(relation: &mut R, + a: &ty::ExistentialBounds<'tcx>, + b: &ty::ExistentialBounds<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { let r = relation.with_cause( Cause::ExistentialRegionBound, |relation| relation.relate_with_variance(ty::Contravariant, &a.region_bound, - &b.region_bound))?; - let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds)?; - let pb = relation.relate(&a.projection_bounds, &b.projection_bounds)?; + &b.region_bound, + side_effects))?; + let nb = relation.relate(&a.builtin_bounds, &b.builtin_bounds, side_effects)?; + let pb = relation.relate(&a.projection_bounds, &b.projection_bounds, side_effects)?; Ok(ty::ExistentialBounds { region_bound: r, builtin_bounds: nb, projection_bounds: pb }) } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BuiltinBounds { - fn relate(relation: &mut R, - a: &ty::BuiltinBounds, - b: &ty::BuiltinBounds) - -> RelateResult<'tcx, ty::BuiltinBounds> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::BuiltinBounds { + fn relate(relation: &mut R, + a: &ty::BuiltinBounds, + b: &ty::BuiltinBounds, + _: &mut S) + -> RelateResult<'tcx, ty::BuiltinBounds> + where R: TypeRelation<'a, 'tcx, S> { // Two sets of builtin bounds are only relatable if they are // precisely the same (but see the coercion code). @@ -407,42 +436,45 @@ impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BuiltinBounds { } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TraitRef<'tcx> { - fn relate(relation: &mut R, - a: &ty::TraitRef<'tcx>, - b: &ty::TraitRef<'tcx>) - -> RelateResult<'tcx, ty::TraitRef<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::TraitRef<'tcx> { + fn relate(relation: &mut R, + a: &ty::TraitRef<'tcx>, + b: &ty::TraitRef<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::TraitRef<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { // Different traits cannot be related if a.def_id != b.def_id { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { - let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs)?; + let substs = relate_item_substs(relation, a.def_id, a.substs, b.substs, side_effects)?; Ok(ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) }) } } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for Ty<'tcx> { - fn relate(relation: &mut R, - a: &Ty<'tcx>, - b: &Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for Ty<'tcx> { + fn relate(relation: &mut R, + a: &Ty<'tcx>, + b: &Ty<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { - relation.tys(a, b) + relation.tys(a, b, side_effects) } } /// The main "type relation" routine. Note that this does not handle /// inference artifacts, so you should filter those out before calling /// it. -pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, - a: Ty<'tcx>, - b: Ty<'tcx>) - -> RelateResult<'tcx, Ty<'tcx>> - where R: TypeRelation<'a,'tcx> +pub fn super_relate_tys<'a, 'tcx, R, S>(relation: &mut R, + a: Ty<'tcx>, + b: Ty<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, Ty<'tcx>> + where R: TypeRelation<'a, 'tcx, S>, 'tcx: 'a { let tcx = relation.tcx(); let a_sty = &a.sty; @@ -481,21 +513,29 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TyEnum(a_def, a_substs), &ty::TyEnum(b_def, b_substs)) if a_def == b_def => { - let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?; + let substs = relate_item_substs(relation, + a_def.did, + a_substs, + b_substs, + side_effects)?; Ok(tcx.mk_enum(a_def, tcx.mk_substs(substs))) } (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) => { - let principal = relation.relate(&a_.principal, &b_.principal)?; - let bounds = relation.relate(&a_.bounds, &b_.bounds)?; + let principal = relation.relate(&a_.principal, &b_.principal, side_effects)?; + let bounds = relation.relate(&a_.bounds, &b_.bounds, side_effects)?; Ok(tcx.mk_trait(principal, bounds)) } (&ty::TyStruct(a_def, a_substs), &ty::TyStruct(b_def, b_substs)) if a_def == b_def => { - let substs = relate_item_substs(relation, a_def.did, a_substs, b_substs)?; + let substs = relate_item_substs(relation, + a_def.did, + a_substs, + b_substs, + side_effects)?; Ok(tcx.mk_struct(a_def, tcx.mk_substs(substs))) } @@ -506,32 +546,35 @@ 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 = relation.relate(a_substs, b_substs)?; + let substs = relation.relate(a_substs, b_substs, side_effects)?; Ok(tcx.mk_closure_from_closure_substs(a_id, substs)) } (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) => { - let typ = relation.relate(&a_inner, &b_inner)?; + let typ = relation.relate(&a_inner, &b_inner, side_effects)?; Ok(tcx.mk_box(typ)) } (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) => { - let mt = relation.relate(a_mt, b_mt)?; + let mt = relation.relate(a_mt, b_mt, side_effects)?; Ok(tcx.mk_ptr(mt)) } (&ty::TyRef(a_r, ref a_mt), &ty::TyRef(b_r, ref b_mt)) => { - let r = relation.relate_with_variance(ty::Contravariant, a_r, b_r)?; - let mt = relation.relate(a_mt, b_mt)?; + let r = relation.relate_with_variance(ty::Contravariant, + a_r, + b_r, + side_effects)?; + let mt = relation.relate(a_mt, b_mt, side_effects)?; Ok(tcx.mk_ref(tcx.mk_region(r), mt)) } (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) => { - let t = relation.relate(&a_t, &b_t)?; + let t = relation.relate(&a_t, &b_t, side_effects)?; if sz_a == sz_b { Ok(tcx.mk_array(t, sz_a)) } else { @@ -541,7 +584,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, (&ty::TySlice(a_t), &ty::TySlice(b_t)) => { - let t = relation.relate(&a_t, &b_t)?; + let t = relation.relate(&a_t, &b_t, side_effects)?; Ok(tcx.mk_slice(t)) } @@ -549,7 +592,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, { if as_.len() == bs.len() { let ts = as_.iter().zip(bs) - .map(|(a, b)| relation.relate(a, b)) + .map(|(a, b)| relation.relate(a, b, side_effects)) .collect::>()?; Ok(tcx.mk_tup(ts)) } else if !(as_.is_empty() || bs.is_empty()) { @@ -564,20 +607,20 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, &ty::TyFnDef(b_def_id, b_substs, b_fty)) if a_def_id == b_def_id => { - let substs = relate_substs(relation, None, a_substs, b_substs)?; - let fty = relation.relate(a_fty, b_fty)?; + let substs = relate_substs(relation, None, a_substs, b_substs, side_effects)?; + let fty = relation.relate(a_fty, b_fty, side_effects)?; Ok(tcx.mk_fn_def(a_def_id, tcx.mk_substs(substs), fty)) } (&ty::TyFnPtr(a_fty), &ty::TyFnPtr(b_fty)) => { - let fty = relation.relate(a_fty, b_fty)?; + let fty = relation.relate(a_fty, b_fty, side_effects)?; Ok(tcx.mk_fn_ptr(fty)) } (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; + let projection_ty = relation.relate(a_data, b_data, side_effects)?; Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) } @@ -588,82 +631,91 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ClosureSubsts<'tcx> { - fn relate(relation: &mut R, - a: &ty::ClosureSubsts<'tcx>, - b: &ty::ClosureSubsts<'tcx>) - -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::ClosureSubsts<'tcx> { + fn relate(relation: &mut R, + a: &ty::ClosureSubsts<'tcx>, + b: &ty::ClosureSubsts<'tcx>, + side_effects: &mut S) + -> RelateResult<'tcx, ty::ClosureSubsts<'tcx>> + where R: TypeRelation<'a, 'tcx, S> { - let func_substs = relate_substs(relation, None, a.func_substs, b.func_substs)?; - let upvar_tys = relation.relate_zip(&a.upvar_tys, &b.upvar_tys)?; + let func_substs = relate_substs(relation, + None, + a.func_substs, + b.func_substs, + side_effects)?; + let upvar_tys = relation.relate_zip(&a.upvar_tys, &b.upvar_tys, side_effects)?; Ok(ty::ClosureSubsts { func_substs: relation.tcx().mk_substs(func_substs), upvar_tys: upvar_tys }) } } -impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::Region { - fn relate(relation: &mut R, - a: &ty::Region, - b: &ty::Region) - -> RelateResult<'tcx, ty::Region> - where R: TypeRelation<'a,'tcx> +impl<'a, 'tcx: 'a> Relate<'a, 'tcx> for ty::Region { + fn relate(relation: &mut R, + a: &ty::Region, + b: &ty::Region, + side_effects: &mut S) + -> RelateResult<'tcx, ty::Region> + where R: TypeRelation<'a, 'tcx, S> { - relation.regions(*a, *b) + relation.regions(*a, *b, side_effects) } } -impl<'a,'tcx:'a,T> Relate<'a,'tcx> for ty::Binder +impl<'a, 'tcx: 'a, T> Relate<'a, 'tcx> for ty::Binder where T: Relate<'a,'tcx> { - fn relate(relation: &mut R, - a: &ty::Binder, - b: &ty::Binder) - -> RelateResult<'tcx, ty::Binder> - where R: TypeRelation<'a,'tcx> + fn relate(relation: &mut R, + a: &ty::Binder, + b: &ty::Binder, + side_effects: &mut S) + -> RelateResult<'tcx, ty::Binder> + where R: TypeRelation<'a, 'tcx, S> { - relation.binders(a, b) + relation.binders(a, b, side_effects) } } -impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Rc +impl<'a, 'tcx:'a, T> Relate<'a, 'tcx> for Rc where T: Relate<'a,'tcx> { - fn relate(relation: &mut R, - a: &Rc, - b: &Rc) - -> RelateResult<'tcx, Rc> - where R: TypeRelation<'a,'tcx> + fn relate(relation: &mut R, + a: &Rc, + b: &Rc, + side_effects: &mut S) + -> RelateResult<'tcx, Rc> + where R: TypeRelation<'a, 'tcx, S> { let a: &T = a; let b: &T = b; - Ok(Rc::new(relation.relate(a, b)?)) + Ok(Rc::new(relation.relate(a, b, side_effects)?)) } } -impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Box +impl<'a, 'tcx: 'a, T> Relate<'a, 'tcx> for Box where T: Relate<'a,'tcx> { - fn relate(relation: &mut R, - a: &Box, - b: &Box) - -> RelateResult<'tcx, Box> - where R: TypeRelation<'a,'tcx> + fn relate(relation: &mut R, + a: &Box, + b: &Box, + side_effects: &mut S) + -> RelateResult<'tcx, Box> + where R: TypeRelation<'a, 'tcx, S> { let a: &T = a; let b: &T = b; - Ok(Box::new(relation.relate(a, b)?)) + Ok(Box::new(relation.relate(a, b, side_effects)?)) } } /////////////////////////////////////////////////////////////////////////// // Error handling -pub fn expected_found<'a,'tcx:'a,R,T>(relation: &mut R, - a: &T, - b: &T) - -> ExpectedFound - where R: TypeRelation<'a,'tcx>, T: Clone +pub fn expected_found<'a, 'tcx: 'a, R, S, T>(relation: &mut R, + a: &T, + b: &T) + -> ExpectedFound + where R: TypeRelation<'a, 'tcx, S>, T: Clone { expected_found_bool(relation.a_is_expected(), a, b) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8620d5e1fd03c..002c4610af3df 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -22,7 +22,7 @@ use rustc::middle::resolve_lifetime; use rustc::middle::stability; use rustc::ty::subst; use rustc::ty::subst::Subst; -use rustc::traits::ProjectionMode; +use rustc::traits::{PredicateObligations, ProjectionMode}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::ty::relate::TypeRelation; use rustc::infer::{self, TypeOrigin}; @@ -358,25 +358,26 @@ impl<'a, 'tcx> Env<'a, 'tcx> { infer::TypeTrace::dummy(self.tcx()) } - pub fn sub(&self) -> Sub<'a, 'tcx> { + pub fn with_sub) -> T>(&self, mut f: F) -> T { let trace = self.dummy_type_trace(); - self.infcx.sub(true, trace) + f(self.infcx.sub(true, trace)) } - pub fn lub(&self) -> Lub<'a, 'tcx> { + pub fn with_lub) -> T>(&self, mut f: F) -> T { let trace = self.dummy_type_trace(); - self.infcx.lub(true, trace) + f(self.infcx.lub(true, trace)) } - pub fn glb(&self) -> Glb<'a, 'tcx> { + pub fn with_glb) -> T>(&self, mut f: F) -> T { let trace = self.dummy_type_trace(); - self.infcx.glb(true, trace) + f(self.infcx.glb(true, trace)) } /// Checks that `t1 <: t2` is true (this may register additional /// region checks). pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub().relate(&t1, &t2) { + let mut obligations = PredicateObligations::new(); + match self.with_sub(|mut sub| sub.relate(&t1, &t2, &mut obligations)) { Ok(_) => {} Err(ref e) => { panic!("unexpected error computing sub({:?},{:?}): {}", t1, t2, e); @@ -387,7 +388,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `t1 <: t2` is false (this may register additional /// region checks). pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) { - match self.sub().relate(&t1, &t2) { + let mut obligations = PredicateObligations::new(); + match self.with_sub(|mut sub| sub.relate(&t1, &t2, &mut obligations)) { Err(_) => {} Ok(_) => { panic!("unexpected success computing sub({:?},{:?})", t1, t2); @@ -397,7 +399,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `LUB(t1,t2) == t_lub` pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) { - match self.lub().relate(&t1, &t2) { + let mut obligations = PredicateObligations::new(); + match self.with_lub(|mut lub| lub.relate(&t1, &t2, &mut obligations)) { Ok(t) => { self.assert_eq(t, t_lub); } @@ -410,7 +413,8 @@ impl<'a, 'tcx> Env<'a, 'tcx> { /// Checks that `GLB(t1,t2) == t_glb` pub fn check_glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_glb: Ty<'tcx>) { debug!("check_glb(t1={}, t2={}, t_glb={})", t1, t2, t_glb); - match self.glb().relate(&t1, &t2) { + let mut obligations = PredicateObligations::new(); + match self.with_glb(|mut glb| glb.relate(&t1, &t2, &mut obligations)) { Err(e) => { panic!("unexpected error computing LUB: {:?}", e) } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 6cfde27ac97b6..495bac33cda72 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -12,7 +12,7 @@ #![allow(unreachable_code)] use rustc::dep_graph::DepNode; -use rustc::infer::{self, InferCtxt}; +use rustc::infer::{self, InferCtxt, InferOk}; use rustc::traits::{self, ProjectionMode}; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; @@ -336,15 +336,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn mk_subty(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>) -> infer::UnitResult<'tcx> { - infer::mk_subty(self.infcx, false, infer::TypeOrigin::Misc(span), - sup, sub) + infer::mk_subty(self.infcx, false, infer::TypeOrigin::Misc(span), sup, sub) + .map(|InferOk { obligations }| { + // FIXME propagate obligations + assert!(obligations.is_empty()); + () + }) } fn mk_eqty(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>) -> infer::UnitResult<'tcx> { - infer::mk_eqty(self.infcx, false, infer::TypeOrigin::Misc(span), - a, b) + infer::mk_eqty(self.infcx, false, infer::TypeOrigin::Misc(span), a, b) + .map(|InferOk { obligations }| { + // FIXME propagate obligations + assert!(obligations.is_empty()); + () + }) } fn tcx(&self) -> &'a TyCtxt<'tcx> { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index dad7d7cd26ca3..3618f0d61a4cb 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -63,7 +63,7 @@ use check::{autoderef, FnCtxt, UnresolvedTypeAction}; use rustc::infer::{Coercion, TypeOrigin, TypeTrace}; -use rustc::traits::{self, ObligationCause}; +use rustc::traits::{self, ObligationCause, PredicateObligations}; use rustc::traits::{predicate_for_trait_def, report_selection_error}; use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef}; use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer}; @@ -116,11 +116,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let infcx = self.fcx.infcx(); infcx.commit_if_ok(|_| { let trace = TypeTrace::types(self.origin, false, a, b); - if self.use_lub { - infcx.lub(false, trace).relate(&a, &b) + let mut obligations = PredicateObligations::new(); + let result = if self.use_lub { + infcx.lub(false, trace).relate(&a, &b, &mut obligations) } else { - infcx.sub(false, trace).relate(&a, &b) - } + infcx.sub(false, trace).relate(&a, &b, &mut obligations) + }; + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); + result }) } @@ -649,6 +653,7 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>, debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty); let trace = TypeTrace::types(origin, true, prev_ty, new_ty); + let mut obligations = PredicateObligations::new(); let mut lub = fcx.infcx().lub(true, trace); // Special-case that coercion alone cannot handle: @@ -657,13 +662,17 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>, (&ty::TyFnDef(a_def_id, a_substs, a_fty), &ty::TyFnDef(b_def_id, b_substs, b_fty)) => { // The signature must always match. - let fty = lub.relate(a_fty, b_fty)?; + let fty = lub.relate(a_fty, b_fty, &mut obligations)?; + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); if a_def_id == b_def_id { // Same function, maybe the parameters match. let substs = fcx.infcx().commit_if_ok(|_| { - relate_substs(&mut lub, None, a_substs, b_substs) + relate_substs(&mut lub, None, a_substs, b_substs, &mut obligations) }).map(|s| fcx.tcx().mk_substs(s)); + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); if let Ok(substs) = substs { // We have a LUB of prev_ty and new_ty, just return it. @@ -724,7 +733,11 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>, }; if !noop { - return fcx.infcx().commit_if_ok(|_| lub.relate(&prev_ty, &new_ty)); + let result = + fcx.infcx().commit_if_ok(|_| lub.relate(&prev_ty, &new_ty, &mut obligations)); + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); + return result; } } @@ -734,7 +747,13 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>, if let Some(e) = first_error { Err(e) } else { - fcx.infcx().commit_if_ok(|_| lub.relate(&prev_ty, &new_ty)) + fcx.infcx().commit_if_ok(|_| { + let mut obligations = PredicateObligations::new(); + let result = lub.relate(&prev_ty, &new_ty, &mut obligations); + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); + result + }) } } Ok((ty, adjustment)) => { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 6d429fa7b73a1..bfcda95bdcd42 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -9,7 +9,7 @@ // except according to those terms. use middle::free_region::FreeRegionMap; -use rustc::infer::{self, TypeOrigin}; +use rustc::infer::{self, InferOk, TypeOrigin}; use rustc::ty::{self, TyCtxt}; use rustc::traits::{self, ProjectionMode}; use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace}; @@ -475,7 +475,10 @@ pub fn compare_const_impl<'tcx>(tcx: &TyCtxt<'tcx>, }); match err { - Ok(()) => { } + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(terr) => { debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}", impl_ty, @@ -485,7 +488,6 @@ pub fn compare_const_impl<'tcx>(tcx: &TyCtxt<'tcx>, trait: {}", trait_c.name, terr); - return; } } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4b42846297b16..41a940f295409 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,12 +16,10 @@ use super::suggest; use check; use check::{FnCtxt, UnresolvedTypeAction}; use middle::def_id::DefId; -use rustc::ty::subst; -use rustc::ty::subst::Subst; +use rustc::ty::subst::{self, Subst}; use rustc::traits; use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::infer; -use rustc::infer::{InferCtxt, TypeOrigin}; +use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin}; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; use rustc_front::hir; @@ -1135,6 +1133,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> { fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> { self.infcx().sub_types(false, TypeOrigin::Misc(DUMMY_SP), sub, sup) + .map(|InferOk { obligations }| { + // FIXME propagate obligations + assert!(obligations.is_empty()); + () + }) } 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 c5a0657594eb2..22dbcccbe43ab 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,11 +88,10 @@ use middle::astconv_util::prohibit_type_params; use middle::cstore::LOCAL_CRATE; use middle::def::{self, Def}; use middle::def_id::DefId; -use rustc::infer; -use rustc::infer::{TypeOrigin, TypeTrace, type_variable}; +use rustc::infer::{self, InferOk, TypeOrigin, TypeTrace, type_variable}; use middle::pat_util::{self, pat_id_map}; +use rustc::traits::{self, report_fulfillment_errors, ProjectionMode, PredicateObligations}; use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace}; -use rustc::traits::{self, report_fulfillment_errors, ProjectionMode}; use rustc::ty::{GenericPredicates, TypeScheme}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; @@ -1629,6 +1628,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sup: Ty<'tcx>) -> Result<(), TypeError<'tcx>> { infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup) + .map(|InferOk { obligations }| { + // FIXME propagate obligations + assert!(obligations.is_empty()); + () + }) } pub fn mk_eqty(&self, @@ -1638,6 +1642,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sup: Ty<'tcx>) -> Result<(), TypeError<'tcx>> { infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup) + .map(|InferOk { obligations }| { + // FIXME propagate obligations + assert!(obligations.is_empty()); + () + }) } pub fn mk_subr(&self, @@ -1916,7 +1925,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match infer::mk_eqty(self.infcx(), false, TypeOrigin::Misc(default.origin_span), ty, default.ty) { - Ok(()) => {} + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(_) => { conflicts.push((*ty, default)); } @@ -2009,7 +2021,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match infer::mk_eqty(self.infcx(), false, TypeOrigin::Misc(default.origin_span), ty, default.ty) { - Ok(()) => {} + Ok(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + } Err(_) => { result = Some(default); } @@ -2904,7 +2919,12 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, } else { fcx.infcx().commit_if_ok(|_| { let trace = TypeTrace::types(origin, true, then_ty, else_ty); - fcx.infcx().lub(true, trace).relate(&then_ty, &else_ty) + let mut obligations = PredicateObligations::new(); + let result = + fcx.infcx().lub(true, trace).relate(&then_ty, &else_ty, &mut obligations); + // FIXME Propagate side-effect obligations + assert!(obligations.is_empty()); + result }) }; (origin, then_ty, else_ty, result) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 533d24686e71f..cff47509cd935 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -92,7 +92,8 @@ use middle::region::{self, CodeExtent}; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, MethodCall, TypeFoldable}; -use rustc::infer::{self, GenericKind, InferCtxt, SubregionOrigin, TypeOrigin, VerifyBound}; +use rustc::infer::{self, GenericKind, InferCtxt, InferOk, SubregionOrigin, TypeOrigin, + VerifyBound}; use middle::pat_util; use rustc::ty::adjustment; use rustc::ty::wf::ImpliedBound; @@ -1846,7 +1847,11 @@ 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(InferOk { obligations }) => { + // FIXME propagate obligations + assert!(obligations.is_empty()); + Ok(outlives.1) + } Err(_) => { Err(()) } } });