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