]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/lub.rs
New upstream version 1.70.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
AL
4use super::lattice::{self, LatticeDir};
5use super::Subtype;
353b0b11 6use super::{DefineOpaqueTypes, InferCtxt};
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
dfeec247
XL
32 fn tcx(&self) -> TyCtxt<'tcx> {
33 self.fields.tcx()
34 }
1a4d82fc 35
dfeec247
XL
36 fn param_env(&self) -> ty::ParamEnv<'tcx> {
37 self.fields.param_env
38 }
416331ca 39
dfeec247
XL
40 fn a_is_expected(&self) -> bool {
41 self.a_is_expected
42 }
1a4d82fc 43
dfeec247
XL
44 fn relate_with_variance<T: Relate<'tcx>>(
45 &mut self,
46 variance: ty::Variance,
17df50a5 47 _info: ty::VarianceDiagInfo<'tcx>,
f035d41b
XL
48 a: T,
49 b: T,
dfeec247 50 ) -> RelateResult<'tcx, T> {
c34b1796 51 match variance {
5bcae85e 52 ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
c34b1796 53 ty::Covariant => self.relate(a, b),
cc61c64b 54 // FIXME(#41044) -- not correct, need test
1b1a35ee 55 ty::Bivariant => Ok(a),
5bcae85e 56 ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
1a4d82fc
JJ
57 }
58 }
59
c34b1796
AL
60 fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
61 lattice::super_lattice_tys(self, a, b)
1a4d82fc
JJ
62 }
63
dfeec247
XL
64 fn regions(
65 &mut self,
66 a: ty::Region<'tcx>,
67 b: ty::Region<'tcx>,
68 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
69 debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
1a4d82fc 70
94222f64 71 let origin = Subtype(Box::new(self.fields.trace.clone()));
9ffffee4
FG
72 // LUB(&'static u8, &'a u8) == &RegionGLB('static, 'a) u8 == &'a u8
73 Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
74b04a01
XL
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 {
9c376795
FG
97 // LUB of a binder and itself is just itself
98 if a == b {
99 return Ok(a);
100 }
101
abe05a73 102 debug!("binders(a={:?}, b={:?})", a, b);
923072b8
FG
103 if a.skip_binder().has_escaping_bound_vars() || b.skip_binder().has_escaping_bound_vars() {
104 // When higher-ranked types are involved, computing the LUB is
105 // very challenging, switch to invariance. This is obviously
106 // overly conservative but works ok in practice.
107 self.relate_with_variance(
108 ty::Variance::Invariant,
109 ty::VarianceDiagInfo::default(),
110 a,
111 b,
112 )?;
113 Ok(a)
114 } else {
115 Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
116 }
1a4d82fc 117 }
c34b1796 118}
1a4d82fc 119
dc9dc135 120impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
2b03887a 121 fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
c34b1796
AL
122 self.fields.infcx
123 }
124
476ff2be
SL
125 fn cause(&self) -> &ObligationCause<'tcx> {
126 &self.fields.trace.cause
127 }
128
5bcae85e
SL
129 fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
130 let mut sub = self.fields.sub(self.a_is_expected);
f035d41b
XL
131 sub.relate(a, v)?;
132 sub.relate(b, v)?;
c34b1796 133 Ok(())
1a4d82fc 134 }
5e7ed085 135
353b0b11 136 fn define_opaque_types(&self) -> DefineOpaqueTypes {
5e7ed085
FG
137 self.fields.define_opaque_types
138 }
1a4d82fc 139}
9ffffee4
FG
140
141impl<'tcx> ObligationEmittingRelation<'tcx> for Lub<'_, '_, 'tcx> {
142 fn register_predicates(&mut self, obligations: impl IntoIterator<Item: ty::ToPredicate<'tcx>>) {
143 self.fields.register_predicates(obligations);
144 }
145
146 fn register_obligations(&mut self, obligations: PredicateObligations<'tcx>) {
147 self.fields.register_obligations(obligations)
148 }
353b0b11
FG
149
150 fn alias_relate_direction(&self) -> ty::AliasRelationDirection {
151 // FIXME(deferred_projection_equality): This isn't right, I think?
152 ty::AliasRelationDirection::Equate
153 }
9ffffee4 154}