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