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