]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/lub.rs
Auto merge of #101679 - compiler-errors:rpitit-default-body, r=nikomatsakis
[rust.git] / compiler / rustc_infer / src / infer / lub.rs
1 //! Least upper 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 /// "Least upper bound" (common supertype)
14 pub struct Lub<'combine, 'infcx, 'tcx> {
15     fields: &'combine mut CombineFields<'infcx, 'tcx>,
16     a_is_expected: bool,
17 }
18
19 impl<'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> {
24         Lub { fields, a_is_expected }
25     }
26 }
27
28 impl<'tcx> TypeRelation<'tcx> for Lub<'_, '_, 'tcx> {
29     fn tag(&self) -> &'static str {
30         "Lub"
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.glb(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().lub_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 LUB 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<'tcx> ConstEquateRelation<'tcx> for Lub<'_, '_, 'tcx> {
116     fn const_equate_obligation(&mut self, a: ty::Const<'tcx>, b: ty::Const<'tcx>) {
117         self.fields.add_const_equate_obligation(self.a_is_expected, a, b);
118     }
119 }
120
121 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
122     fn infcx(&self) -> &'infcx InferCtxt<'tcx> {
123         self.fields.infcx
124     }
125
126     fn cause(&self) -> &ObligationCause<'tcx> {
127         &self.fields.trace.cause
128     }
129
130     fn add_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>) {
131         self.fields.obligations.extend(obligations)
132     }
133
134     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
135         let mut sub = self.fields.sub(self.a_is_expected);
136         sub.relate(a, v)?;
137         sub.relate(b, v)?;
138         Ok(())
139     }
140
141     fn define_opaque_types(&self) -> bool {
142         self.fields.define_opaque_types
143     }
144 }