]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/relate_tys.rs
Re-use TypeChecker instead of passing around some of its fields
[rust.git] / compiler / rustc_borrowck / src / type_check / relate_tys.rs
1 use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate};
2 use rustc_infer::infer::NllRegionVariableOrigin;
3 use rustc_middle::mir::ConstraintCategory;
4 use rustc_middle::ty::relate::TypeRelation;
5 use rustc_middle::ty::{self, Const, Ty};
6 use rustc_trait_selection::traits::query::Fallible;
7
8 use crate::constraints::OutlivesConstraint;
9 use crate::diagnostics::UniverseInfo;
10 use crate::type_check::{Locations, TypeChecker};
11
12 /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`:
13 ///
14 /// - "Covariant" `a <: b`
15 /// - "Invariant" `a == b`
16 /// - "Contravariant" `a :> b`
17 ///
18 /// N.B., the type `a` is permitted to have unresolved inference
19 /// variables, but not the type `b`.
20 #[instrument(skip(type_checker), level = "debug")]
21 pub(super) fn relate_types<'tcx>(
22     type_checker: &mut TypeChecker<'_, 'tcx>,
23     a: Ty<'tcx>,
24     v: ty::Variance,
25     b: Ty<'tcx>,
26     locations: Locations,
27     category: ConstraintCategory,
28 ) -> Fallible<()> {
29     TypeRelating::new(
30         type_checker.infcx,
31         NllTypeRelatingDelegate::new(type_checker, locations, category, UniverseInfo::relate(a, b)),
32         v,
33     )
34     .relate(a, b)?;
35     Ok(())
36 }
37
38 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
39     type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
40
41     /// Where (and why) is this relation taking place?
42     locations: Locations,
43
44     /// What category do we assign the resulting `'a: 'b` relationships?
45     category: ConstraintCategory,
46
47     /// Information so that error reporting knows what types we are relating
48     /// when reporting a bound region error.
49     universe_info: UniverseInfo<'tcx>,
50 }
51
52 impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
53     fn new(
54         type_checker: &'me mut TypeChecker<'bccx, 'tcx>,
55         locations: Locations,
56         category: ConstraintCategory,
57         universe_info: UniverseInfo<'tcx>,
58     ) -> Self {
59         Self { type_checker, locations, category, universe_info }
60     }
61 }
62
63 impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
64     fn param_env(&self) -> ty::ParamEnv<'tcx> {
65         self.type_checker.param_env
66     }
67
68     fn create_next_universe(&mut self) -> ty::UniverseIndex {
69         let universe = self.type_checker.infcx.create_next_universe();
70         self.type_checker
71             .borrowck_context
72             .constraints
73             .universe_causes
74             .insert(universe, self.universe_info.clone());
75         universe
76     }
77
78     fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
79         let origin = NllRegionVariableOrigin::Existential { from_forall };
80         self.type_checker.infcx.next_nll_region_var(origin)
81     }
82
83     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
84         self.type_checker
85             .borrowck_context
86             .constraints
87             .placeholder_region(self.type_checker.infcx, placeholder)
88     }
89
90     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
91         self.type_checker.infcx.next_nll_region_var_in_universe(
92             NllRegionVariableOrigin::Existential { from_forall: false },
93             universe,
94         )
95     }
96
97     fn push_outlives(
98         &mut self,
99         sup: ty::Region<'tcx>,
100         sub: ty::Region<'tcx>,
101         info: ty::VarianceDiagInfo<'tcx>,
102     ) {
103         let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub);
104         let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup);
105         self.type_checker.borrowck_context.constraints.outlives_constraints.push(
106             OutlivesConstraint {
107                 sup,
108                 sub,
109                 locations: self.locations,
110                 category: self.category,
111                 variance_info: info,
112             },
113         );
114     }
115
116     // We don't have to worry about the equality of consts during borrow checking
117     // as consts always have a static lifetime.
118     fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {}
119
120     fn normalization() -> NormalizationStrategy {
121         NormalizationStrategy::Eager
122     }
123
124     fn forbid_inference_vars() -> bool {
125         true
126     }
127 }