Move a_is_expected
out of CombineFields
This commit is contained in:
parent
5e390322c3
commit
dddaf34cfc
8 changed files with 86 additions and 82 deletions
|
@ -33,12 +33,13 @@ use ty::TyVar;
|
||||||
use ty::relate::{Relate, RelateResult, TypeRelation};
|
use ty::relate::{Relate, RelateResult, TypeRelation};
|
||||||
|
|
||||||
pub struct Bivariate<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct Bivariate<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
fields: CombineFields<'infcx, 'gcx, 'tcx>
|
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
||||||
|
a_is_expected: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> Bivariate<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> Bivariate<'infcx, 'gcx, 'tcx> {
|
||||||
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>) -> Bivariate<'infcx, 'gcx, 'tcx> {
|
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool) -> Bivariate<'infcx, 'gcx, 'tcx> {
|
||||||
Bivariate { fields: fields }
|
Bivariate { fields: fields, a_is_expected: a_is_expected }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Bivariate<'infcx,
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
||||||
|
|
||||||
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
|
fn a_is_expected(&self) -> bool { self.a_is_expected }
|
||||||
|
|
||||||
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
||||||
variance: ty::Variance,
|
variance: ty::Variance,
|
||||||
|
@ -86,12 +87,12 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Bivariate<'infcx,
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::TyInfer(TyVar(a_id)), _) => {
|
(&ty::TyInfer(TyVar(a_id)), _) => {
|
||||||
self.fields.instantiate(b, BiTo, a_id)?;
|
self.fields.instantiate(b, BiTo, a_id, self.a_is_expected)?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, &ty::TyInfer(TyVar(b_id))) => {
|
(_, &ty::TyInfer(TyVar(b_id))) => {
|
||||||
self.fields.instantiate(a, BiTo, b_id)?;
|
self.fields.instantiate(a, BiTo, b_id, self.a_is_expected)?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ use syntax_pos::Span;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct CombineFields<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
|
pub infcx: &'infcx InferCtxt<'infcx, 'gcx, 'tcx>,
|
||||||
pub a_is_expected: bool,
|
|
||||||
pub trace: TypeTrace<'tcx>,
|
pub trace: TypeTrace<'tcx>,
|
||||||
pub cause: Option<ty::relate::Cause>,
|
pub cause: Option<ty::relate::Cause>,
|
||||||
pub obligations: PredicateObligations<'tcx>,
|
pub obligations: PredicateObligations<'tcx>,
|
||||||
|
@ -155,37 +154,31 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
|
||||||
self.infcx.tcx
|
self.infcx.tcx
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switch_expected(&self) -> CombineFields<'infcx, 'gcx, 'tcx> {
|
pub fn equate(&self, a_is_expected: bool) -> Equate<'infcx, 'gcx, 'tcx> {
|
||||||
CombineFields {
|
Equate::new(self.clone(), a_is_expected)
|
||||||
a_is_expected: !self.a_is_expected,
|
|
||||||
..(*self).clone()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equate(&self) -> Equate<'infcx, 'gcx, 'tcx> {
|
pub fn bivariate(&self, a_is_expected: bool) -> Bivariate<'infcx, 'gcx, 'tcx> {
|
||||||
Equate::new(self.clone())
|
Bivariate::new(self.clone(), a_is_expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bivariate(&self) -> Bivariate<'infcx, 'gcx, 'tcx> {
|
pub fn sub(&self, a_is_expected: bool) -> Sub<'infcx, 'gcx, 'tcx> {
|
||||||
Bivariate::new(self.clone())
|
Sub::new(self.clone(), a_is_expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub(&self) -> Sub<'infcx, 'gcx, 'tcx> {
|
pub fn lub(&self, a_is_expected: bool) -> Lub<'infcx, 'gcx, 'tcx> {
|
||||||
Sub::new(self.clone())
|
Lub::new(self.clone(), a_is_expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lub(&self) -> Lub<'infcx, 'gcx, 'tcx> {
|
pub fn glb(&self, a_is_expected: bool) -> Glb<'infcx, 'gcx, 'tcx> {
|
||||||
Lub::new(self.clone())
|
Glb::new(self.clone(), a_is_expected)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn glb(&self) -> Glb<'infcx, 'gcx, 'tcx> {
|
|
||||||
Glb::new(self.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn instantiate(&self,
|
pub fn instantiate(&self,
|
||||||
a_ty: Ty<'tcx>,
|
a_ty: Ty<'tcx>,
|
||||||
dir: RelationDir,
|
dir: RelationDir,
|
||||||
b_vid: ty::TyVid)
|
b_vid: ty::TyVid,
|
||||||
|
a_is_expected: bool)
|
||||||
-> RelateResult<'tcx, ()>
|
-> RelateResult<'tcx, ()>
|
||||||
{
|
{
|
||||||
let mut stack = Vec::new();
|
let mut stack = Vec::new();
|
||||||
|
@ -255,10 +248,10 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
|
||||||
// to associate causes/spans with each of the relations in
|
// to associate causes/spans with each of the relations in
|
||||||
// the stack to get this right.
|
// the stack to get this right.
|
||||||
match dir {
|
match dir {
|
||||||
BiTo => self.bivariate().relate(&a_ty, &b_ty),
|
BiTo => self.bivariate(a_is_expected).relate(&a_ty, &b_ty),
|
||||||
EqTo => self.equate().relate(&a_ty, &b_ty),
|
EqTo => self.equate(a_is_expected).relate(&a_ty, &b_ty),
|
||||||
SubtypeOf => self.sub().relate(&a_ty, &b_ty),
|
SubtypeOf => self.sub(a_is_expected).relate(&a_ty, &b_ty),
|
||||||
SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
|
SupertypeOf => self.sub(a_is_expected).relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,13 @@ use traits::PredicateObligations;
|
||||||
|
|
||||||
/// Ensures `a` is made equal to `b`. Returns `a` on success.
|
/// Ensures `a` is made equal to `b`. Returns `a` on success.
|
||||||
pub struct Equate<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct Equate<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
fields: CombineFields<'infcx, 'gcx, 'tcx>
|
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
||||||
|
a_is_expected: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> Equate<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> Equate<'infcx, 'gcx, 'tcx> {
|
||||||
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>) -> Equate<'infcx, 'gcx, 'tcx> {
|
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool) -> Equate<'infcx, 'gcx, 'tcx> {
|
||||||
Equate { fields: fields }
|
Equate { fields: fields, a_is_expected: a_is_expected }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
||||||
|
@ -37,7 +38,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Equate<'infcx, 'gc
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
||||||
|
|
||||||
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
|
fn a_is_expected(&self) -> bool { self.a_is_expected }
|
||||||
|
|
||||||
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
||||||
_: ty::Variance,
|
_: ty::Variance,
|
||||||
|
@ -63,12 +64,12 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Equate<'infcx, 'gc
|
||||||
}
|
}
|
||||||
|
|
||||||
(&ty::TyInfer(TyVar(a_id)), _) => {
|
(&ty::TyInfer(TyVar(a_id)), _) => {
|
||||||
self.fields.instantiate(b, EqTo, a_id)?;
|
self.fields.instantiate(b, EqTo, a_id, self.a_is_expected)?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
(_, &ty::TyInfer(TyVar(b_id))) => {
|
(_, &ty::TyInfer(TyVar(b_id))) => {
|
||||||
self.fields.instantiate(a, EqTo, b_id)?;
|
self.fields.instantiate(a, EqTo, b_id, self.a_is_expected)?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +94,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Equate<'infcx, 'gc
|
||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
self.fields.higher_ranked_sub(a, b)?;
|
self.fields.higher_ranked_sub(a, b, self.a_is_expected)?;
|
||||||
self.fields.higher_ranked_sub(b, a)
|
self.fields.higher_ranked_sub(b, a, self.a_is_expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,13 @@ use traits::PredicateObligations;
|
||||||
|
|
||||||
/// "Greatest lower bound" (common subtype)
|
/// "Greatest lower bound" (common subtype)
|
||||||
pub struct Glb<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct Glb<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
fields: CombineFields<'infcx, 'gcx, 'tcx>
|
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
||||||
|
a_is_expected: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> Glb<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> Glb<'infcx, 'gcx, 'tcx> {
|
||||||
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>) -> Glb<'infcx, 'gcx, 'tcx> {
|
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool) -> Glb<'infcx, 'gcx, 'tcx> {
|
||||||
Glb { fields: fields }
|
Glb { fields: fields, a_is_expected: a_is_expected }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
||||||
|
@ -37,7 +38,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Glb<'infcx, 'gcx,
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
||||||
|
|
||||||
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
|
fn a_is_expected(&self) -> bool { self.a_is_expected }
|
||||||
|
|
||||||
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
||||||
variance: ty::Variance,
|
variance: ty::Variance,
|
||||||
|
@ -46,10 +47,10 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Glb<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, T>
|
-> RelateResult<'tcx, T>
|
||||||
{
|
{
|
||||||
match variance {
|
match variance {
|
||||||
ty::Invariant => self.fields.equate().relate(a, b),
|
ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
|
||||||
ty::Covariant => self.relate(a, b),
|
ty::Covariant => self.relate(a, b),
|
||||||
ty::Bivariant => self.fields.bivariate().relate(a, b),
|
ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
|
||||||
ty::Contravariant => self.fields.lub().relate(a, b),
|
ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Glb<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
self.fields.higher_ranked_glb(a, b)
|
self.fields.higher_ranked_glb(a, b, self.a_is_expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ impl<'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx> for Glb<'infcx, 'gcx, 't
|
||||||
}
|
}
|
||||||
|
|
||||||
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>) -> RelateResult<'tcx, ()> {
|
||||||
let mut sub = self.fields.sub();
|
let mut sub = self.fields.sub(self.a_is_expected);
|
||||||
sub.relate(&v, &a)?;
|
sub.relate(&v, &a)?;
|
||||||
sub.relate(&v, &b)?;
|
sub.relate(&v, &b)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -40,7 +40,7 @@ pub struct HrMatchResult<U> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
pub fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
|
pub fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
|
||||||
-> RelateResult<'tcx, Binder<T>>
|
-> RelateResult<'tcx, Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
|
@ -77,11 +77,11 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
debug!("b_prime={:?}", b_prime);
|
debug!("b_prime={:?}", b_prime);
|
||||||
|
|
||||||
// Compare types now that bound regions have been replaced.
|
// Compare types now that bound regions have been replaced.
|
||||||
let result = self.sub().relate(&a_prime, &b_prime)?;
|
let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
|
||||||
|
|
||||||
// Presuming type comparison succeeds, we need to check
|
// Presuming type comparison succeeds, we need to check
|
||||||
// that the skolemized regions do not "leak".
|
// that the skolemized regions do not "leak".
|
||||||
self.infcx.leak_check(!self.a_is_expected, span, &skol_map, snapshot)?;
|
self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
|
||||||
|
|
||||||
// We are finished with the skolemized regions now so pop
|
// We are finished with the skolemized regions now so pop
|
||||||
// them off.
|
// them off.
|
||||||
|
@ -109,7 +109,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
pub fn higher_ranked_match<T, U>(&self,
|
pub fn higher_ranked_match<T, U>(&self,
|
||||||
span: Span,
|
span: Span,
|
||||||
a_pair: &Binder<(T, U)>,
|
a_pair: &Binder<(T, U)>,
|
||||||
b_match: &T)
|
b_match: &T,
|
||||||
|
a_is_expected: bool)
|
||||||
-> RelateResult<'tcx, HrMatchResult<U>>
|
-> RelateResult<'tcx, HrMatchResult<U>>
|
||||||
where T: Relate<'tcx>,
|
where T: Relate<'tcx>,
|
||||||
U: TypeFoldable<'tcx>
|
U: TypeFoldable<'tcx>
|
||||||
|
@ -129,7 +130,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
debug!("higher_ranked_match: skol_map={:?}", skol_map);
|
debug!("higher_ranked_match: skol_map={:?}", skol_map);
|
||||||
|
|
||||||
// Equate types now that bound regions have been replaced.
|
// Equate types now that bound regions have been replaced.
|
||||||
try!(self.equate().relate(&a_match, &b_match));
|
try!(self.equate(a_is_expected).relate(&a_match, &b_match));
|
||||||
|
|
||||||
// Map each skolemized region to a vector of other regions that it
|
// Map each skolemized region to a vector of other regions that it
|
||||||
// must be equated with. (Note that this vector may include other
|
// must be equated with. (Note that this vector may include other
|
||||||
|
@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>)
|
pub fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
|
||||||
-> RelateResult<'tcx, Binder<T>>
|
-> RelateResult<'tcx, Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
|
@ -239,7 +240,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Collect constraints.
|
// Collect constraints.
|
||||||
let result0 =
|
let result0 =
|
||||||
self.lub().relate(&a_with_fresh, &b_with_fresh)?;
|
self.lub(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
|
||||||
let result0 =
|
let result0 =
|
||||||
self.infcx.resolve_type_vars_if_possible(&result0);
|
self.infcx.resolve_type_vars_if_possible(&result0);
|
||||||
debug!("lub result0 = {:?}", result0);
|
debug!("lub result0 = {:?}", result0);
|
||||||
|
@ -311,7 +312,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>)
|
pub fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>, a_is_expected: bool)
|
||||||
-> RelateResult<'tcx, Binder<T>>
|
-> RelateResult<'tcx, Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
|
@ -333,7 +334,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
|
|
||||||
// Collect constraints.
|
// Collect constraints.
|
||||||
let result0 =
|
let result0 =
|
||||||
self.glb().relate(&a_with_fresh, &b_with_fresh)?;
|
self.glb(a_is_expected).relate(&a_with_fresh, &b_with_fresh)?;
|
||||||
let result0 =
|
let result0 =
|
||||||
self.infcx.resolve_type_vars_if_possible(&result0);
|
self.infcx.resolve_type_vars_if_possible(&result0);
|
||||||
debug!("glb result0 = {:?}", result0);
|
debug!("glb result0 = {:?}", result0);
|
||||||
|
|
|
@ -19,12 +19,13 @@ use traits::PredicateObligations;
|
||||||
|
|
||||||
/// "Least upper bound" (common supertype)
|
/// "Least upper bound" (common supertype)
|
||||||
pub struct Lub<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct Lub<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
fields: CombineFields<'infcx, 'gcx, 'tcx>
|
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
||||||
|
a_is_expected: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> Lub<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> Lub<'infcx, 'gcx, 'tcx> {
|
||||||
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>) -> Lub<'infcx, 'gcx, 'tcx> {
|
pub fn new(fields: CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool) -> Lub<'infcx, 'gcx, 'tcx> {
|
||||||
Lub { fields: fields }
|
Lub { fields: fields, a_is_expected: a_is_expected }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
||||||
|
@ -37,7 +38,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Lub<'infcx, 'gcx,
|
||||||
|
|
||||||
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.tcx() }
|
||||||
|
|
||||||
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
|
fn a_is_expected(&self) -> bool { self.a_is_expected }
|
||||||
|
|
||||||
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
fn relate_with_variance<T: Relate<'tcx>>(&mut self,
|
||||||
variance: ty::Variance,
|
variance: ty::Variance,
|
||||||
|
@ -46,10 +47,10 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Lub<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, T>
|
-> RelateResult<'tcx, T>
|
||||||
{
|
{
|
||||||
match variance {
|
match variance {
|
||||||
ty::Invariant => self.fields.equate().relate(a, b),
|
ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
|
||||||
ty::Covariant => self.relate(a, b),
|
ty::Covariant => self.relate(a, b),
|
||||||
ty::Bivariant => self.fields.bivariate().relate(a, b),
|
ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
|
||||||
ty::Contravariant => self.fields.glb().relate(a, b),
|
ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Lub<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
self.fields.higher_ranked_lub(a, b)
|
self.fields.higher_ranked_lub(a, b, self.a_is_expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@ impl<'infcx, 'gcx, 'tcx> LatticeDir<'infcx, 'gcx, 'tcx> for Lub<'infcx, 'gcx, 't
|
||||||
}
|
}
|
||||||
|
|
||||||
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>) -> RelateResult<'tcx, ()> {
|
||||||
let mut sub = self.fields.sub();
|
let mut sub = self.fields.sub(self.a_is_expected);
|
||||||
sub.relate(&a, &v)?;
|
sub.relate(&a, &v)?;
|
||||||
sub.relate(&b, &v)?;
|
sub.relate(&b, &v)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -799,11 +799,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
return variables;
|
return variables;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
|
fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
|
||||||
-> CombineFields<'a, 'gcx, 'tcx> {
|
-> CombineFields<'a, 'gcx, 'tcx> {
|
||||||
CombineFields {
|
CombineFields {
|
||||||
infcx: self,
|
infcx: self,
|
||||||
a_is_expected: a_is_expected,
|
|
||||||
trace: trace,
|
trace: trace,
|
||||||
cause: None,
|
cause: None,
|
||||||
obligations: PredicateObligations::new(),
|
obligations: PredicateObligations::new(),
|
||||||
|
@ -814,7 +813,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut equate = self.combine_fields(a_is_expected, trace).equate();
|
let mut equate = self.combine_fields(trace).equate(a_is_expected);
|
||||||
let result = equate.relate(a, b);
|
let result = equate.relate(a, b);
|
||||||
result.map(|t| InferOk { value: t, obligations: equate.obligations() })
|
result.map(|t| InferOk { value: t, obligations: equate.obligations() })
|
||||||
}
|
}
|
||||||
|
@ -823,7 +822,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut sub = self.combine_fields(a_is_expected, trace).sub();
|
let mut sub = self.combine_fields(trace).sub(a_is_expected);
|
||||||
let result = sub.relate(a, b);
|
let result = sub.relate(a, b);
|
||||||
result.map(|t| InferOk { value: t, obligations: sub.obligations() })
|
result.map(|t| InferOk { value: t, obligations: sub.obligations() })
|
||||||
}
|
}
|
||||||
|
@ -832,7 +831,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut lub = self.combine_fields(a_is_expected, trace).lub();
|
let mut lub = self.combine_fields(trace).lub(a_is_expected);
|
||||||
let result = lub.relate(a, b);
|
let result = lub.relate(a, b);
|
||||||
result.map(|t| InferOk { value: t, obligations: lub.obligations() })
|
result.map(|t| InferOk { value: t, obligations: lub.obligations() })
|
||||||
}
|
}
|
||||||
|
@ -841,7 +840,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
-> InferResult<'tcx, T>
|
-> InferResult<'tcx, T>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
let mut glb = self.combine_fields(a_is_expected, trace).glb();
|
let mut glb = self.combine_fields(trace).glb(a_is_expected);
|
||||||
let result = glb.relate(a, b);
|
let result = glb.relate(a, b);
|
||||||
result.map(|t| InferOk { value: t, obligations: glb.obligations() })
|
result.map(|t| InferOk { value: t, obligations: glb.obligations() })
|
||||||
}
|
}
|
||||||
|
@ -1646,8 +1645,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
|
let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
|
||||||
let combine = self.combine_fields(true, trace);
|
let combine = self.combine_fields(trace);
|
||||||
let result = combine.higher_ranked_match(span, &match_pair, &match_b)?;
|
let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
|
||||||
Ok(InferOk { value: result, obligations: combine.obligations })
|
Ok(InferOk { value: result, obligations: combine.obligations })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,22 +21,30 @@ use std::mem;
|
||||||
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
|
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
|
||||||
pub struct Sub<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
pub struct Sub<'infcx, 'gcx: 'infcx+'tcx, 'tcx: 'infcx> {
|
||||||
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
fields: CombineFields<'infcx, 'gcx, 'tcx>,
|
||||||
|
a_is_expected: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> Sub<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> Sub<'infcx, 'gcx, 'tcx> {
|
||||||
pub fn new(f: CombineFields<'infcx, 'gcx, 'tcx>) -> Sub<'infcx, 'gcx, 'tcx> {
|
pub fn new(f: CombineFields<'infcx, 'gcx, 'tcx>, a_is_expected: bool) -> Sub<'infcx, 'gcx, 'tcx> {
|
||||||
Sub { fields: f }
|
Sub { fields: f, a_is_expected: a_is_expected }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
pub fn obligations(self) -> PredicateObligations<'tcx> {
|
||||||
self.fields.obligations
|
self.fields.obligations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_expected_switched<R, F: FnOnce(&mut Self) -> R>(&mut self, f: F) -> R {
|
||||||
|
self.a_is_expected = !self.a_is_expected;
|
||||||
|
let result = f(self);
|
||||||
|
self.a_is_expected = !self.a_is_expected;
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'infcx, 'gcx, 'tcx> {
|
impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'infcx, 'gcx, 'tcx> {
|
||||||
fn tag(&self) -> &'static str { "Sub" }
|
fn tag(&self) -> &'static str { "Sub" }
|
||||||
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
|
fn tcx(&self) -> TyCtxt<'infcx, 'gcx, 'tcx> { self.fields.infcx.tcx }
|
||||||
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
|
fn a_is_expected(&self) -> bool { self.a_is_expected }
|
||||||
|
|
||||||
fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
|
fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
|
||||||
where F: FnOnce(&mut Self) -> R
|
where F: FnOnce(&mut Self) -> R
|
||||||
|
@ -56,10 +64,10 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, T>
|
-> RelateResult<'tcx, T>
|
||||||
{
|
{
|
||||||
match variance {
|
match variance {
|
||||||
ty::Invariant => self.fields.equate().relate(a, b),
|
ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
|
||||||
ty::Covariant => self.relate(a, b),
|
ty::Covariant => self.relate(a, b),
|
||||||
ty::Bivariant => self.fields.bivariate().relate(a, b),
|
ty::Bivariant => self.fields.bivariate(self.a_is_expected).relate(a, b),
|
||||||
ty::Contravariant => self.fields.switch_expected().sub().relate(b, a),
|
ty::Contravariant => self.with_expected_switched(|this| { this.relate(b, a) }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,12 +88,11 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'infcx, 'gcx,
|
||||||
}
|
}
|
||||||
(&ty::TyInfer(TyVar(a_id)), _) => {
|
(&ty::TyInfer(TyVar(a_id)), _) => {
|
||||||
self.fields
|
self.fields
|
||||||
.switch_expected()
|
.instantiate(b, SupertypeOf, a_id, !self.a_is_expected)?;
|
||||||
.instantiate(b, SupertypeOf, a_id)?;
|
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
(_, &ty::TyInfer(TyVar(b_id))) => {
|
(_, &ty::TyInfer(TyVar(b_id))) => {
|
||||||
self.fields.instantiate(a, SubtypeOf, b_id)?;
|
self.fields.instantiate(a, SubtypeOf, b_id, self.a_is_expected)?;
|
||||||
Ok(a)
|
Ok(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +123,6 @@ impl<'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> for Sub<'infcx, 'gcx,
|
||||||
-> RelateResult<'tcx, ty::Binder<T>>
|
-> RelateResult<'tcx, ty::Binder<T>>
|
||||||
where T: Relate<'tcx>
|
where T: Relate<'tcx>
|
||||||
{
|
{
|
||||||
self.fields.higher_ranked_sub(a, b)
|
self.fields.higher_ranked_sub(a, b, self.a_is_expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue