]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_infer/src/infer/glb.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_infer / src / infer / glb.rs
CommitLineData
5e7ed085
FG
1//! Greatest lower bound. See [`lattice`].
2
c34b1796 3use super::combine::CombineFields;
c34b1796 4use super::lattice::{self, LatticeDir};
dfeec247 5use super::InferCtxt;
85aaf69f 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/// "Greatest lower bound" (common subtype)
dc9dc135
XL
14pub struct Glb<'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> 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 28impl<'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 115impl<'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
140impl<'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}