1 use super::combine::CombineFields;
2 use super::lattice::{self, LatticeDir};
6 use crate::infer::combine::ConstEquateRelation;
7 use crate::traits::ObligationCause;
8 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
9 use rustc_middle::ty::{self, Ty, TyCtxt};
11 /// "Greatest lower bound" (common subtype)
12 pub struct Glb<'combine, 'infcx, 'tcx> {
13 fields: &'combine mut CombineFields<'infcx, 'tcx>,
17 impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> {
19 fields: &'combine mut CombineFields<'infcx, 'tcx>,
21 ) -> Glb<'combine, 'infcx, 'tcx> {
22 Glb { fields, a_is_expected }
26 impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
27 fn tag(&self) -> &'static str {
31 fn tcx(&self) -> TyCtxt<'tcx> {
35 fn param_env(&self) -> ty::ParamEnv<'tcx> {
39 fn a_is_expected(&self) -> bool {
43 fn relate_with_variance<T: Relate<'tcx>>(
45 variance: ty::Variance,
46 _info: ty::VarianceDiagInfo<'tcx>,
49 ) -> RelateResult<'tcx, T> {
51 ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
52 ty::Covariant => self.relate(a, b),
53 // FIXME(#41044) -- not correct, need test
54 ty::Bivariant => Ok(a),
55 ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
59 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
60 lattice::super_lattice_tys(self, a, b)
67 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
68 debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
70 let origin = Subtype(Box::new(self.fields.trace.clone()));
71 Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
81 a: &'tcx ty::Const<'tcx>,
82 b: &'tcx ty::Const<'tcx>,
83 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
84 self.fields.infcx.super_combine_consts(self, a, b)
89 a: ty::Binder<'tcx, T>,
90 b: ty::Binder<'tcx, T>,
91 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
95 debug!("binders(a={:?}, b={:?})", a, b);
97 // When higher-ranked types are involved, computing the LUB is
98 // very challenging, switch to invariance. This is obviously
99 // overly conservative but works ok in practice.
100 self.relate_with_variance(ty::Variance::Invariant, ty::VarianceDiagInfo::default(), a, b)?;
105 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
106 fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> {
110 fn cause(&self) -> &ObligationCause<'tcx> {
111 &self.fields.trace.cause
114 fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
115 let mut sub = self.fields.sub(self.a_is_expected);
122 impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
123 fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) {
124 self.fields.add_const_equate_obligation(self.a_is_expected, a, b);