]> git.lizzy.rs Git - rust.git/blob - src/librustc_traits/chalk_context/unify.rs
Rollup merge of #67867 - matthewjasper:opaque-assoc-lookup, r=oli-obk
[rust.git] / src / librustc_traits / chalk_context / unify.rs
1 use rustc::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
2 use rustc::infer::{InferCtxt, RegionVariableOrigin};
3 use rustc::traits::{DomainGoal, Environment, Goal, InEnvironment};
4 use rustc::ty;
5 use rustc::ty::relate::{Relate, RelateResult, TypeRelation};
6 use rustc_span::DUMMY_SP;
7
8 crate struct UnificationResult<'tcx> {
9     crate goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>,
10     crate constraints: Vec<super::RegionConstraint<'tcx>>,
11 }
12
13 crate fn unify<'me, 'tcx, T: Relate<'tcx>>(
14     infcx: &'me InferCtxt<'me, 'tcx>,
15     environment: Environment<'tcx>,
16     variance: ty::Variance,
17     a: &T,
18     b: &T,
19 ) -> RelateResult<'tcx, UnificationResult<'tcx>> {
20     debug!(
21         "unify(
22         a = {:?},
23         b = {:?},
24         environment = {:?},
25     )",
26         a, b, environment
27     );
28
29     let mut delegate = ChalkTypeRelatingDelegate::new(infcx, environment);
30
31     TypeRelating::new(infcx, &mut delegate, variance).relate(a, b)?;
32
33     debug!("unify: goals = {:?}, constraints = {:?}", delegate.goals, delegate.constraints);
34
35     Ok(UnificationResult { goals: delegate.goals, constraints: delegate.constraints })
36 }
37
38 struct ChalkTypeRelatingDelegate<'me, 'tcx> {
39     infcx: &'me InferCtxt<'me, 'tcx>,
40     environment: Environment<'tcx>,
41     goals: Vec<InEnvironment<'tcx, Goal<'tcx>>>,
42     constraints: Vec<super::RegionConstraint<'tcx>>,
43 }
44
45 impl ChalkTypeRelatingDelegate<'me, 'tcx> {
46     fn new(infcx: &'me InferCtxt<'me, 'tcx>, environment: Environment<'tcx>) -> Self {
47         Self { infcx, environment, goals: Vec::new(), constraints: Vec::new() }
48     }
49 }
50
51 impl TypeRelatingDelegate<'tcx> for &mut ChalkTypeRelatingDelegate<'_, 'tcx> {
52     fn create_next_universe(&mut self) -> ty::UniverseIndex {
53         self.infcx.create_next_universe()
54     }
55
56     fn next_existential_region_var(&mut self, _was_placeholder: bool) -> ty::Region<'tcx> {
57         self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP))
58     }
59
60     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
61         self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder))
62     }
63
64     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
65         self.infcx
66             .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(DUMMY_SP), universe)
67     }
68
69     fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
70         self.constraints.push(ty::OutlivesPredicate(sup.into(), sub));
71     }
72
73     fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>) {
74         let goal = self.environment.with(self.infcx.tcx.mk_goal(domain_goal.into_goal()));
75         self.goals.push(goal);
76     }
77
78     fn normalization() -> NormalizationStrategy {
79         NormalizationStrategy::Lazy
80     }
81
82     fn forbid_inference_vars() -> bool {
83         false
84     }
85 }