use traits::ObligationCause;
use ty::{self, Ty, TyCtxt};
+use ty::error::TypeError;
use ty::relate::{Relate, RelateResult, TypeRelation};
/// "Greatest lower bound" (common subtype)
b);
let origin = Subtype(self.fields.trace.clone());
- Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b))
+ Ok(self.fields.infcx.borrow_region_constraints().glb_regions(self.tcx(), origin, a, b))
}
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'tcx>
{
- self.fields.higher_ranked_glb(a, b, self.a_is_expected)
+ debug!("binders(a={:?}, b={:?})", a, b);
+ let was_error = self.infcx().probe(|_snapshot| {
+ // Subtle: use a fresh combine-fields here because we recover
+ // from Err. Doing otherwise could propagate obligations out
+ // through our `self.obligations` field.
+ self.infcx()
+ .combine_fields(self.fields.trace.clone(), self.fields.param_env)
+ .higher_ranked_glb(a, b, self.a_is_expected)
+ .is_err()
+ });
+ debug!("binders: was_error={:?}", was_error);
+
+ // When higher-ranked types are involved, computing the LUB is
+ // very challenging, switch to invariance. This is obviously
+ // overly conservative but works ok in practice.
+ match self.relate_with_variance(ty::Variance::Invariant, a, b) {
+ Ok(_) => Ok(a.clone()),
+ Err(err) => {
+ debug!("binders: error occurred, was_error={:?}", was_error);
+ if !was_error {
+ Err(TypeError::OldStyleLUB(Box::new(err)))
+ } else {
+ Err(err)
+ }
+ }
+ }
}
}