]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/lub.rs
Auto merge of #68391 - tmiasko:compiletest-debuginfo, r=alexcrichton
[rust.git] / src / librustc / infer / lub.rs
1 use super::combine::CombineFields;
2 use super::lattice::{self, LatticeDir};
3 use super::InferCtxt;
4 use super::Subtype;
5
6 use crate::traits::ObligationCause;
7 use crate::ty::relate::{Relate, RelateResult, TypeRelation};
8 use crate::ty::{self, Ty, TyCtxt};
9
10 /// "Least upper bound" (common supertype)
11 pub struct Lub<'combine, 'infcx, 'tcx> {
12     fields: &'combine mut CombineFields<'infcx, 'tcx>,
13     a_is_expected: bool,
14 }
15
16 impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> {
17     pub fn new(
18         fields: &'combine mut CombineFields<'infcx, 'tcx>,
19         a_is_expected: bool,
20     ) -> Lub<'combine, 'infcx, 'tcx> {
21         Lub { fields: fields, a_is_expected: a_is_expected }
22     }
23 }
24
25 impl TypeRelation<'tcx> for Lub<'combine, 'infcx, 'tcx> {
26     fn tag(&self) -> &'static str {
27         "Lub"
28     }
29
30     fn tcx(&self) -> TyCtxt<'tcx> {
31         self.fields.tcx()
32     }
33
34     fn param_env(&self) -> ty::ParamEnv<'tcx> {
35         self.fields.param_env
36     }
37
38     fn a_is_expected(&self) -> bool {
39         self.a_is_expected
40     }
41
42     fn relate_with_variance<T: Relate<'tcx>>(
43         &mut self,
44         variance: ty::Variance,
45         a: &T,
46         b: &T,
47     ) -> RelateResult<'tcx, T> {
48         match variance {
49             ty::Invariant => self.fields.equate(self.a_is_expected).relate(a, b),
50             ty::Covariant => self.relate(a, b),
51             // FIXME(#41044) -- not correct, need test
52             ty::Bivariant => Ok(a.clone()),
53             ty::Contravariant => self.fields.glb(self.a_is_expected).relate(a, b),
54         }
55     }
56
57     fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
58         lattice::super_lattice_tys(self, a, b)
59     }
60
61     fn regions(
62         &mut self,
63         a: ty::Region<'tcx>,
64         b: ty::Region<'tcx>,
65     ) -> RelateResult<'tcx, ty::Region<'tcx>> {
66         debug!("{}.regions({:?}, {:?})", self.tag(), a, b);
67
68         let origin = Subtype(box self.fields.trace.clone());
69         Ok(self.fields.infcx.borrow_region_constraints().lub_regions(self.tcx(), origin, a, b))
70     }
71
72     fn consts(
73         &mut self,
74         a: &'tcx ty::Const<'tcx>,
75         b: &'tcx ty::Const<'tcx>,
76     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
77         self.fields.infcx.super_combine_consts(self, a, b)
78     }
79
80     fn binders<T>(
81         &mut self,
82         a: &ty::Binder<T>,
83         b: &ty::Binder<T>,
84     ) -> RelateResult<'tcx, ty::Binder<T>>
85     where
86         T: Relate<'tcx>,
87     {
88         debug!("binders(a={:?}, b={:?})", a, b);
89
90         // When higher-ranked types are involved, computing the LUB is
91         // very challenging, switch to invariance. This is obviously
92         // overly conservative but works ok in practice.
93         self.relate_with_variance(ty::Variance::Invariant, a, b)?;
94         Ok(a.clone())
95     }
96 }
97
98 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Lub<'combine, 'infcx, 'tcx> {
99     fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> {
100         self.fields.infcx
101     }
102
103     fn cause(&self) -> &ObligationCause<'tcx> {
104         &self.fields.trace.cause
105     }
106
107     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
108         let mut sub = self.fields.sub(self.a_is_expected);
109         sub.relate(&a, &v)?;
110         sub.relate(&b, &v)?;
111         Ok(())
112     }
113 }