]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/lub.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / lub.rs
CommitLineData
5e7ed085
FG
1//! Least upper bound. See [`lattice`].
2
9ffffee4 3use super::combine::{CombineFields, ObligationEmittingRelation};
c34b1796 4use super::lattice::{self, LatticeDir};
dfeec247 5use super::InferCtxt;
c34b1796 6use super::Subtype;
1a4d82fc 7
9ffffee4 8use crate::traits::{ObligationCause, PredicateObligations};
ba9703b0 9use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
9ffffee4 10use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
1a4d82fc
JJ
11
12/// "Least upper bound" (common supertype)
dc9dc135
XL
13pub struct Lub<'combine, 'infcx, 'tcx> {
14 fields: &'combine mut CombineFields<'infcx, 'tcx>,
5bcae85e 15 a_is_expected: bool,
1a4d82fc
JJ
16}
17
dc9dc135
XL
18impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
19 pub fn new(
20 fields: &'combine mut CombineFields<'infcx, 'tcx>,
21 a_is_expected: bool,
22 ) -> Lub<'combine, 'infcx, 'tcx> {
74b04a01 23 Lub { fields, a_is_expected }
54a0048b 24 }
c34b1796 25}
1a4d82fc 26
a2a8927a 27impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
dfeec247
XL
28 fn tag(&self) -> &'static str {
29 "Lub"
30 }
1a4d82fc 31
487cf647
FG
32 fn intercrate(&self) -> bool {
33 assert!(!self.fields.infcx.intercrate);
34 false
35 }
36
dfeec247
XL
37 fn tcx(&self) -> TyCtxt<'tcx> {
38 self.fields.tcx()
39 }
1a4d82fc 40
dfeec247
XL
41 fn param_env(&self) -> ty::ParamEnv<'tcx> {
42 self.fields.param_env
43 }
416331ca 44
dfeec247
XL
45 fn a_is_expected(&self) -> bool {
46 self.a_is_expected
47 }
1a4d82fc 48
487cf647
FG
49 fn mark_ambiguous(&mut self) {
50 bug!("mark_ambiguous used outside of coherence");
51 }
52
dfeec247
XL
53 fn relate_with_variance<T: Relate<'tcx>>(
54 &mut self,
55 variance: ty::Variance,
17df50a5 56 _info: ty::VarianceDiagInfo<'tcx>,
f035d41b
XL
57 a: T,
58 b: T,
dfeec247 59 ) -> RelateResult<'tcx, T> {
c34b1796 60 match variance {
5bcae85e 61 ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
c34b1796 62 ty::Covariant => self.relate(a, b),
cc61c64b 63 // FIXME(#41044) -- not correct, need test
1b1a35ee 64 ty::Bivariant => Ok(a),
5bcae85e 65 ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
1a4d82fc
JJ
66 }
67 }
68
c34b1796
AL
69 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
70 lattice::super_lattice_tys(self, a, b)
1a4d82fc
JJ
71 }
72
dfeec247
XL
73 fn regions(
74 &mut self,
75 a: ty::Region<'tcx>,
76 b: ty::Region<'tcx>,
77 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
78 debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
1a4d82fc 79
94222f64 80 let origin = Subtype(Box::new(self.fields.trace.clone()));
9ffffee4
FG
81 // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
82 Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
74b04a01
XL
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
dc9dc135 129impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
2b03887a 130 fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
c34b1796
AL
131 self.fields.infcx
132 }
133
476ff2be
SL
134 fn cause(&self) -> &ObligationCause<'tcx> {
135 &self.fields.trace.cause
136 }
137
5bcae85e
SL
138 fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
139 let mut sub = self.fields.sub(self.a_is_expected);
f035d41b
XL
140 sub.relate(a, v)?;
141 sub.relate(b, v)?;
c34b1796 142 Ok(())
1a4d82fc 143 }
5e7ed085
FG
144
145 fn define_opaque_types(&self) -> bool {
146 self.fields.define_opaque_types
147 }
1a4d82fc 148}
9ffffee4
FG
149
150impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
151 fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
152 self.fields.register_predicates(obligations);
153 }
154
155 fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
156 self.fields.register_obligations(obligations)
157 }
158}