]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/glb.rs
Rollup merge of #102641 - eholk:dyn-star-box, r=compiler-errors
[rust.git] / compiler / rustc_infer / src / infer / glb.rs
1 //! Greatest lower bound. See [`lattice`].
2
3 use super::combine::CombineFields;
4 use super::lattice::{self, LatticeDir};
5 use super::InferCtxt;
6 use super::Subtype;
7
8 use crate::infer::combine::ConstEquateRelation;
9 use crate::traits::{ObligationCause, PredicateObligation};
10 use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
11 use rustc_middle::ty::{self, Ty, TyCtxt};
12
13 /// "Greatest lower bound" (common subtype)
14 pub struct Glb<'combine, 'infcx, 'tcx> {
15     fields: &'combine mut CombineFields<'infcx, 'tcx>,
16     a_is_expected: bool,
17 }
18
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> {
24         Glb { fields, a_is_expected }
25     }
26 }
27
28 impl<'tcx> TypeRelation<'tcx> for Glb<'_, '_, 'tcx> {
29     fn tag(&self) -> &'static str {
30         "Glb"
31     }
32
33     fn tcx(&self) -> TyCtxt<'tcx> {
34         self.fields.tcx()
35     }
36
37     fn param_env(&self) -> ty::ParamEnv<'tcx> {
38         self.fields.param_env
39     }
40
41     fn a_is_expected(&self) -> bool {
42         self.a_is_expected
43     }
44
45     fn relate_with_variance<T: Relate<'tcx>>(
46         &mut self,
47         variance: ty::Variance,
48         _info: ty::VarianceDiagInfo<'tcx>,
49         a: T,
50         b: T,
51     ) -> RelateResult<'tcx, T> {
52         match variance {
53             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
54             ty::Covariant => self.relate(a, b),
55             // FIXME(#41044) -- not correct, need test
56             ty::Bivariant => Ok(a),
57             ty::Contravariant => self.fields.lub(self.a_is_expected).relate(a, b),
58         }
59     }
60
61     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
62         lattice::super_lattice_tys(self, a, b)
63     }
64
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);
71
72         let origin = Subtype(Box::new(self.fields.trace.clone()));
73         Ok(self.fields.infcx.inner.borrow_mut().unwrap_region_constraints().glb_regions(
74             self.tcx(),
75             origin,
76             a,
77             b,
78         ))
79     }
80
81     fn consts(
82         &mut self,
83         a: ty::Const<'tcx>,
84         b: ty::Const<'tcx>,
85     ) -> RelateResult<'tcx, ty::Const<'tcx>> {
86         self.fields.infcx.super_combine_consts(self, a, b)
87     }
88
89     fn binders<T>(
90         &mut self,
91         a: ty::Binder<'tcx, T>,
92         b: ty::Binder<'tcx, T>,
93     ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
94     where
95         T: Relate<'tcx>,
96     {
97         debug!("binders(a={:?}, b={:?})", a, b);
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         }
112     }
113 }
114
115 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
116     fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
117         self.fields.infcx
118     }
119
120     fn cause(&self) -> &ObligationCause<'tcx> {
121         &self.fields.trace.cause
122     }
123
124     fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
125         self.fields.obligations.extend(obligations)
126     }
127
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);
130         sub.relate(v, a)?;
131         sub.relate(v, b)?;
132         Ok(())
133     }
134
135     fn define_opaque_types(&self) -> bool {
136         self.fields.define_opaque_types
137     }
138 }
139
140 impl<'tcx> ConstEquateRelation<'tcx> for Glb<'_, '_, 'tcx> {
141     fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
142         self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
143     }
144 }