]>
Commit | Line | Data |
---|---|---|
c295e0f8 XL |
1 | use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; |
2 | use rustc_infer::infer::NllRegionVariableOrigin; | |
5e7ed085 | 3 | use rustc_infer::traits::ObligationCause; |
c295e0f8 | 4 | use rustc_middle::mir::ConstraintCategory; |
5e7ed085 | 5 | use rustc_middle::ty::error::TypeError; |
c295e0f8 XL |
6 | use rustc_middle::ty::relate::TypeRelation; |
7 | use rustc_middle::ty::{self, Const, Ty}; | |
5e7ed085 | 8 | use rustc_span::Span; |
c295e0f8 XL |
9 | use rustc_trait_selection::traits::query::Fallible; |
10 | ||
11 | use crate::constraints::OutlivesConstraint; | |
12 | use crate::diagnostics::UniverseInfo; | |
5e7ed085 | 13 | use crate::type_check::{InstantiateOpaqueType, Locations, TypeChecker}; |
c295e0f8 XL |
14 | |
15 | impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | |
16 | /// Adds sufficient constraints to ensure that `a R b` where `R` depends on `v`: | |
17 | /// | |
18 | /// - "Covariant" `a <: b` | |
19 | /// - "Invariant" `a == b` | |
20 | /// - "Contravariant" `a :> b` | |
21 | /// | |
22 | /// N.B., the type `a` is permitted to have unresolved inference | |
23 | /// variables, but not the type `b`. | |
24 | #[instrument(skip(self), level = "debug")] | |
25 | pub(super) fn relate_types( | |
26 | &mut self, | |
27 | a: Ty<'tcx>, | |
28 | v: ty::Variance, | |
29 | b: Ty<'tcx>, | |
30 | locations: Locations, | |
31 | category: ConstraintCategory, | |
32 | ) -> Fallible<()> { | |
33 | TypeRelating::new( | |
34 | self.infcx, | |
35 | NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::relate(a, b)), | |
36 | v, | |
37 | ) | |
38 | .relate(a, b)?; | |
39 | Ok(()) | |
40 | } | |
41 | } | |
42 | ||
43 | struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { | |
44 | type_checker: &'me mut TypeChecker<'bccx, 'tcx>, | |
45 | ||
46 | /// Where (and why) is this relation taking place? | |
47 | locations: Locations, | |
48 | ||
49 | /// What category do we assign the resulting `'a: 'b` relationships? | |
50 | category: ConstraintCategory, | |
51 | ||
52 | /// Information so that error reporting knows what types we are relating | |
53 | /// when reporting a bound region error. | |
54 | universe_info: UniverseInfo<'tcx>, | |
55 | } | |
56 | ||
a2a8927a | 57 | impl<'me, 'bccx, 'tcx> NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { |
c295e0f8 XL |
58 | fn new( |
59 | type_checker: &'me mut TypeChecker<'bccx, 'tcx>, | |
60 | locations: Locations, | |
61 | category: ConstraintCategory, | |
62 | universe_info: UniverseInfo<'tcx>, | |
63 | ) -> Self { | |
64 | Self { type_checker, locations, category, universe_info } | |
65 | } | |
66 | } | |
67 | ||
a2a8927a | 68 | impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { |
5e7ed085 FG |
69 | fn span(&self) -> Span { |
70 | self.locations.span(self.type_checker.body) | |
71 | } | |
72 | ||
c295e0f8 XL |
73 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
74 | self.type_checker.param_env | |
75 | } | |
76 | ||
77 | fn create_next_universe(&mut self) -> ty::UniverseIndex { | |
78 | let universe = self.type_checker.infcx.create_next_universe(); | |
79 | self.type_checker | |
80 | .borrowck_context | |
81 | .constraints | |
82 | .universe_causes | |
83 | .insert(universe, self.universe_info.clone()); | |
84 | universe | |
85 | } | |
86 | ||
87 | fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { | |
88 | let origin = NllRegionVariableOrigin::Existential { from_forall }; | |
89 | self.type_checker.infcx.next_nll_region_var(origin) | |
90 | } | |
91 | ||
92 | fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { | |
93 | self.type_checker | |
94 | .borrowck_context | |
95 | .constraints | |
96 | .placeholder_region(self.type_checker.infcx, placeholder) | |
97 | } | |
98 | ||
99 | fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { | |
100 | self.type_checker.infcx.next_nll_region_var_in_universe( | |
101 | NllRegionVariableOrigin::Existential { from_forall: false }, | |
102 | universe, | |
103 | ) | |
104 | } | |
105 | ||
106 | fn push_outlives( | |
107 | &mut self, | |
108 | sup: ty::Region<'tcx>, | |
109 | sub: ty::Region<'tcx>, | |
110 | info: ty::VarianceDiagInfo<'tcx>, | |
111 | ) { | |
112 | let sub = self.type_checker.borrowck_context.universal_regions.to_region_vid(sub); | |
113 | let sup = self.type_checker.borrowck_context.universal_regions.to_region_vid(sup); | |
114 | self.type_checker.borrowck_context.constraints.outlives_constraints.push( | |
115 | OutlivesConstraint { | |
116 | sup, | |
117 | sub, | |
118 | locations: self.locations, | |
119 | category: self.category, | |
120 | variance_info: info, | |
121 | }, | |
122 | ); | |
123 | } | |
124 | ||
125 | // We don't have to worry about the equality of consts during borrow checking | |
126 | // as consts always have a static lifetime. | |
5e7ed085 FG |
127 | // FIXME(oli-obk): is this really true? We can at least have HKL and with |
128 | // inline consts we may have further lifetimes that may be unsound to treat as | |
129 | // 'static. | |
5099ac24 | 130 | fn const_equate(&mut self, _a: Const<'tcx>, _b: Const<'tcx>) {} |
c295e0f8 XL |
131 | |
132 | fn normalization() -> NormalizationStrategy { | |
133 | NormalizationStrategy::Eager | |
134 | } | |
135 | ||
136 | fn forbid_inference_vars() -> bool { | |
137 | true | |
138 | } | |
5e7ed085 FG |
139 | |
140 | fn register_opaque_type( | |
141 | &mut self, | |
142 | a: Ty<'tcx>, | |
143 | b: Ty<'tcx>, | |
144 | a_is_expected: bool, | |
145 | ) -> Result<(), TypeError<'tcx>> { | |
146 | let param_env = self.param_env(); | |
147 | let span = self.span(); | |
148 | let def_id = self.type_checker.body.source.def_id().expect_local(); | |
149 | let body_id = self.type_checker.tcx().hir().local_def_id_to_hir_id(def_id); | |
150 | let cause = ObligationCause::misc(span, body_id); | |
151 | self.type_checker | |
152 | .fully_perform_op( | |
153 | self.locations, | |
154 | self.category, | |
155 | InstantiateOpaqueType { | |
156 | obligations: self | |
157 | .type_checker | |
158 | .infcx | |
159 | .handle_opaque_type(a, b, a_is_expected, &cause, param_env)? | |
160 | .obligations, | |
161 | // These fields are filled in during execution of the operation | |
162 | base_universe: None, | |
163 | region_constraints: None, | |
164 | }, | |
165 | ) | |
166 | .unwrap(); | |
167 | Ok(()) | |
168 | } | |
c295e0f8 | 169 | } |