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 /// "Least upper bound" (common supertype)
12 pub struct Lub
<'combine
, 'infcx
, 'tcx
> {
13 fields
: &'combine
mut CombineFields
<'infcx
, 'tcx
>,
17 impl<'combine
, 'infcx
, 'tcx
> Lub
<'combine
, 'infcx
, 'tcx
> {
19 fields
: &'combine
mut CombineFields
<'infcx
, 'tcx
>,
21 ) -> Lub
<'combine
, 'infcx
, 'tcx
> {
22 Lub { fields, a_is_expected }
26 impl TypeRelation
<'tcx
> for Lub
<'combine
, 'infcx
, '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
,
48 ) -> RelateResult
<'tcx
, T
> {
50 ty
::Invariant
=> self.fields
.equate(self.a_is_expected
).relate(a
, b
),
51 ty
::Covariant
=> self.relate(a
, b
),
52 // FIXME(#41044) -- not correct, need test
53 ty
::Bivariant
=> Ok(a
),
54 ty
::Contravariant
=> self.fields
.glb(self.a_is_expected
).relate(a
, b
),
58 fn tys(&mut self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, Ty
<'tcx
>> {
59 lattice
::super_lattice_tys(self, a
, b
)
66 ) -> RelateResult
<'tcx
, ty
::Region
<'tcx
>> {
67 debug
!("{}.regions({:?}, {:?})", self.tag(), a
, b
);
69 let origin
= Subtype(box self.fields
.trace
.clone());
70 Ok(self.fields
.infcx
.inner
.borrow_mut().unwrap_region_constraints().lub_regions(
80 a
: &'tcx ty
::Const
<'tcx
>,
81 b
: &'tcx ty
::Const
<'tcx
>,
82 ) -> RelateResult
<'tcx
, &'tcx ty
::Const
<'tcx
>> {
83 self.fields
.infcx
.super_combine_consts(self, a
, b
)
90 ) -> RelateResult
<'tcx
, ty
::Binder
<T
>>
94 debug
!("binders(a={:?}, b={:?})", a
, b
);
96 // When higher-ranked types are involved, computing the LUB is
97 // very challenging, switch to invariance. This is obviously
98 // overly conservative but works ok in practice.
99 self.relate_with_variance(ty
::Variance
::Invariant
, a
, b
)?
;
104 impl<'tcx
> ConstEquateRelation
<'tcx
> for Lub
<'_
, '_
, 'tcx
> {
105 fn const_equate_obligation(&mut self, a
: &'tcx ty
::Const
<'tcx
>, b
: &'tcx ty
::Const
<'tcx
>) {
106 self.fields
.add_const_equate_obligation(self.a_is_expected
, a
, b
);
110 impl<'combine
, 'infcx
, 'tcx
> LatticeDir
<'infcx
, 'tcx
> for Lub
<'combine
, 'infcx
, 'tcx
> {
111 fn infcx(&self) -> &'infcx InferCtxt
<'infcx
, 'tcx
> {
115 fn cause(&self) -> &ObligationCause
<'tcx
> {
116 &self.fields
.trace
.cause
119 fn relate_bound(&mut self, v
: Ty
<'tcx
>, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> RelateResult
<'tcx
, ()> {
120 let mut sub
= self.fields
.sub(self.a_is_expected
);