]>
Commit | Line | Data |
---|---|---|
5e7ed085 FG |
1 | //! Greatest lower bound. See [`lattice`]. |
2 | ||
c34b1796 | 3 | use super::combine::CombineFields; |
c34b1796 | 4 | use super::lattice::{self, LatticeDir}; |
dfeec247 | 5 | use super::InferCtxt; |
85aaf69f | 6 | use super::Subtype; |
1a4d82fc | 7 | |
f9f354fc | 8 | use crate::infer::combine::ConstEquateRelation; |
5e7ed085 | 9 | use crate::traits::{ObligationCause, PredicateObligation}; |
ba9703b0 XL |
10 | use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation}; |
11 | use rustc_middle::ty::{self, Ty, TyCtxt}; | |
1a4d82fc JJ |
12 | |
13 | /// "Greatest lower bound" (common subtype) | |
dc9dc135 XL |
14 | pub struct Glb<'combine, 'infcx, 'tcx> { |
15 | fields: &'combine mut CombineFields<'infcx, 'tcx>, | |
5bcae85e | 16 | a_is_expected: bool, |
1a4d82fc JJ |
17 | } |
18 | ||
dc9dc135 XL |
19 | impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> { |
20 | pub fn new( | |
21 | fields: &'combine mut CombineFields<'infcx, 'tcx>, | |
22 | a_is_expected: bool, | |
23 | ) -> Glb<'combine, 'infcx, 'tcx> { | |
74b04a01 | 24 | Glb { fields, a_is_expected } |
54a0048b | 25 | } |
c34b1796 | 26 | } |
85aaf69f | 27 | |
a2a8927a | 28 | impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> { |
dfeec247 XL |
29 | fn tag(&self) -> &'static str { |
30 | "Glb" | |
31 | } | |
1a4d82fc | 32 | |
dfeec247 XL |
33 | fn tcx(&self) -> TyCtxt<'tcx> { |
34 | self.fields.tcx() | |
35 | } | |
1a4d82fc | 36 | |
dfeec247 XL |
37 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
38 | self.fields.param_env | |
39 | } | |
416331ca | 40 | |
dfeec247 XL |
41 | fn a_is_expected(&self) -> bool { |
42 | self.a_is_expected | |
43 | } | |
1a4d82fc | 44 | |
dfeec247 XL |
45 | fn relate_with_variance<T: Relate<'tcx>>( |
46 | &mut self, | |
47 | variance: ty::Variance, | |
17df50a5 | 48 | _info: ty::VarianceDiagInfo<'tcx>, |
f035d41b XL |
49 | a: T, |
50 | b: T, | |
dfeec247 | 51 | ) -> RelateResult<'tcx, T> { |
c34b1796 | 52 | match variance { |
5bcae85e | 53 | ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b), |
c34b1796 | 54 | ty::Covariant => self.relate(a, b), |
cc61c64b | 55 | // FIXME(#41044) -- not correct, need test |
3dfed10e | 56 | ty::Bivariant => Ok(a), |
5bcae85e | 57 | ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b), |
1a4d82fc JJ |
58 | } |
59 | } | |
60 | ||
c34b1796 AL |
61 | fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
62 | lattice::super_lattice_tys(self, a, b) | |
1a4d82fc JJ |
63 | } |
64 | ||
dfeec247 XL |
65 | fn regions( |
66 | &mut self, | |
67 | a: ty::Region<'tcx>, | |
68 | b: ty::Region<'tcx>, | |
69 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
70 | debug!("{}.regions({:?}, {:?})", self.tag(), a, b); | |
1a4d82fc | 71 | |
94222f64 | 72 | let origin = Subtype(Box::new(self.fields.trace.clone())); |
74b04a01 XL |
73 | Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions( |
74 | self.tcx(), | |
75 | origin, | |
76 | a, | |
77 | b, | |
78 | )) | |
1a4d82fc JJ |
79 | } |
80 | ||
48663c56 XL |
81 | fn consts( |
82 | &mut self, | |
5099ac24 FG |
83 | a: ty::Const<'tcx>, |
84 | b: ty::Const<'tcx>, | |
85 | ) -> RelateResult<'tcx, ty::Const<'tcx>> { | |
48663c56 XL |
86 | self.fields.infcx.super_combine_consts(self, a, b) |
87 | } | |
88 | ||
dfeec247 XL |
89 | fn binders<T>( |
90 | &mut self, | |
cdc7bbd5 XL |
91 | a: ty::Binder<'tcx, T>, |
92 | b: ty::Binder<'tcx, T>, | |
93 | ) -> RelateResult<'tcx, ty::Binder<'tcx, T>> | |
dfeec247 XL |
94 | where |
95 | T: Relate<'tcx>, | |
c34b1796 | 96 | { |
abe05a73 | 97 | debug!("binders(a={:?}, b={:?})", a, b); |
923072b8 FG |
98 | if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() { |
99 | // When higher-ranked types are involved, computing the GLB is | |
100 | // very challenging, switch to invariance. This is obviously | |
101 | // overly conservative but works ok in practice. | |
102 | self.relate_with_variance( | |
103 | ty::Variance::Invariant, | |
104 | ty::VarianceDiagInfo::default(), | |
105 | a, | |
106 | b, | |
107 | )?; | |
108 | Ok(a) | |
109 | } else { | |
110 | Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?)) | |
111 | } | |
1a4d82fc | 112 | } |
c34b1796 | 113 | } |
1a4d82fc | 114 | |
dc9dc135 | 115 | impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> { |
2b03887a | 116 | fn infcx(&self) -> &'infcx InferCtxt<'tcx> { |
c34b1796 AL |
117 | self.fields.infcx |
118 | } | |
119 | ||
476ff2be SL |
120 | fn cause(&self) -> &ObligationCause<'tcx> { |
121 | &self.fields.trace.cause | |
122 | } | |
123 | ||
5e7ed085 FG |
124 | fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) { |
125 | self.fields.obligations.extend(obligations) | |
126 | } | |
127 | ||
5bcae85e SL |
128 | fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> { |
129 | let mut sub = self.fields.sub(self.a_is_expected); | |
f035d41b XL |
130 | sub.relate(v, a)?; |
131 | sub.relate(v, b)?; | |
c34b1796 | 132 | Ok(()) |
1a4d82fc | 133 | } |
5e7ed085 FG |
134 | |
135 | fn define_opaque_types(&self) -> bool { | |
136 | self.fields.define_opaque_types | |
137 | } | |
1a4d82fc | 138 | } |
f9f354fc XL |
139 | |
140 | impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> { | |
5099ac24 | 141 | fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) { |
f9f354fc XL |
142 | self.fields.add_const_equate_obligation(self.a_is_expected, a, b); |
143 | } | |
144 | } |