]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/relate_tys.rs
Rollup merge of #75644 - c410-f3r:array, r=yaahc
[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::{InferCtxt, 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::{BorrowCheckContext, Locations};
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(infcx, param_env, borrowck_context), level = "debug")]
21 pub(super) fn relate_types<'tcx>(
22     infcx: &InferCtxt<'_, 'tcx>,
23     param_env: ty::ParamEnv<'tcx>,
24     a: Ty<'tcx>,
25     v: ty::Variance,
26     b: Ty<'tcx>,
27     locations: Locations,
28     category: ConstraintCategory,
29     borrowck_context: &mut BorrowCheckContext<'_, 'tcx>,
30 ) -> Fallible<()> {
31     TypeRelating::new(
32         infcx,
33         NllTypeRelatingDelegate::new(
34             infcx,
35             borrowck_context,
36             param_env,
37             locations,
38             category,
39             UniverseInfo::relate(a, b),
40         ),
41         v,
42     )
43     .relate(a, b)?;
44     Ok(())
45 }
46
47 struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
48     infcx: &'me InferCtxt<'me, 'tcx>,
49     borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>,
50
51     param_env: ty::ParamEnv<'tcx>,
52
53     /// Where (and why) is this relation taking place?
54     locations: Locations,
55
56     /// What category do we assign the resulting `'a: 'b` relationships?
57     category: ConstraintCategory,
58
59     /// Information so that error reporting knows what types we are relating
60     /// when reporting a bound region error.
61     universe_info: UniverseInfo<'tcx>,
62 }
63
64 impl NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
65     fn new(
66         infcx: &'me InferCtxt<'me, 'tcx>,
67         borrowck_context: &'me mut BorrowCheckContext<'bccx, 'tcx>,
68         param_env: ty::ParamEnv<'tcx>,
69         locations: Locations,
70         category: ConstraintCategory,
71         universe_info: UniverseInfo<'tcx>,
72     ) -> Self {
73         Self { infcx, borrowck_context, param_env, locations, category, universe_info }
74     }
75 }
76
77 impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> {
78     fn param_env(&self) -> ty::ParamEnv<'tcx> {
79         self.param_env
80     }
81
82     fn create_next_universe(&mut self) -> ty::UniverseIndex {
83         let universe = self.infcx.create_next_universe();
84         self.borrowck_context
85             .constraints
86             .universe_causes
87             .insert(universe, self.universe_info.clone());
88         universe
89     }
90
91     fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> {
92         let origin = NllRegionVariableOrigin::Existential { from_forall };
93         self.infcx.next_nll_region_var(origin)
94     }
95
96     fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> {
97         self.borrowck_context.constraints.placeholder_region(self.infcx, placeholder)
98     }
99
100     fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> {
101         self.infcx.next_nll_region_var_in_universe(
102             NllRegionVariableOrigin::Existential { from_forall: false },
103             universe,
104         )
105     }
106
107     fn push_outlives(
108         &mut self,
109         sup: ty::Region<'tcx>,
110         sub: ty::Region<'tcx>,
111         info: ty::VarianceDiagInfo<'tcx>,
112     ) {
113         let sub = self.borrowck_context.universal_regions.to_region_vid(sub);
114         let sup = self.borrowck_context.universal_regions.to_region_vid(sup);
115         self.borrowck_context.constraints.outlives_constraints.push(OutlivesConstraint {
116             sup,
117             sub,
118             locations: self.locations,
119             category: self.category,
120             variance_info: info,
121         });
122     }
123
124     // We don't have to worry about the equality of consts during borrow checking
125     // as consts always have a static lifetime.
126     fn const_equate(&mut self, _a: &'tcx Const<'tcx>, _b: &'tcx Const<'tcx>) {}
127
128     fn normalization() -> NormalizationStrategy {
129         NormalizationStrategy::Eager
130     }
131
132     fn forbid_inference_vars() -> bool {
133         true
134     }
135 }