]> git.lizzy.rs Git - rust.git/blob - src/librustc_infer/infer/glb.rs
Rollup merge of #69011 - foeb:document-unsafe-core-fmt, r=Mark-Simulacrum
[rust.git] / src / librustc_infer / infer / glb.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 rustc::ty::relate::{Relate, RelateResult, TypeRelation};
8 use rustc::ty::{self, Ty, TyCtxt};
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, a_is_expected }
22     }
23 }
24
25 impl TypeRelation<'tcx> for Glb<'combine, 'infcx, 'tcx> {
26     fn tag(&self) -> &'static str {
27         "Glb"
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.lub(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.inner.borrow_mut().unwrap_region_constraints().glb_regions(
70             self.tcx(),
71             origin,
72             a,
73             b,
74         ))
75     }
76
77     fn consts(
78         &mut self,
79         a: &'tcx ty::Const<'tcx>,
80         b: &'tcx ty::Const<'tcx>,
81     ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
82         self.fields.infcx.super_combine_consts(self, a, b)
83     }
84
85     fn binders<T>(
86         &mut self,
87         a: &ty::Binder<T>,
88         b: &ty::Binder<T>,
89     ) -> RelateResult<'tcx, ty::Binder<T>>
90     where
91         T: Relate<'tcx>,
92     {
93         debug!("binders(a={:?}, b={:?})", a, b);
94
95         // When higher-ranked types are involved, computing the LUB is
96         // very challenging, switch to invariance. This is obviously
97         // overly conservative but works ok in practice.
98         self.relate_with_variance(ty::Variance::Invariant, a, b)?;
99         Ok(a.clone())
100     }
101 }
102
103 impl<'combine, 'infcx, 'tcx> LatticeDir<'infcx, 'tcx> for Glb<'combine, 'infcx, 'tcx> {
104     fn infcx(&self) -> &'infcx InferCtxt<'infcx, 'tcx> {
105         self.fields.infcx
106     }
107
108     fn cause(&self) -> &ObligationCause<'tcx> {
109         &self.fields.trace.cause
110     }
111
112     fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
113         let mut sub = self.fields.sub(self.a_is_expected);
114         sub.relate(&v, &a)?;
115         sub.relate(&v, &b)?;
116         Ok(())
117     }
118 }