]>
Commit | Line | Data |
---|---|---|
0bf4aa26 XL |
1 | //! This code is kind of an alternate way of doing subtyping, |
2 | //! supertyping, and type equating, distinct from the `combine.rs` | |
3 | //! code but very similar in its effect and design. Eventually the two | |
a1dfa0c6 | 4 | //! ought to be merged. This code is intended for use in NLL and chalk. |
0bf4aa26 XL |
5 | //! |
6 | //! Here are the key differences: | |
7 | //! | |
0731742a | 8 | //! - This code may choose to bypass some checks (e.g., the occurs check) |
a1dfa0c6 XL |
9 | //! in the case where we know that there are no unbound type inference |
10 | //! variables. This is the case for NLL, because at NLL time types are fully | |
11 | //! inferred up-to regions. | |
0bf4aa26 XL |
12 | //! - This code uses "universes" to handle higher-ranked regions and |
13 | //! not the leak-check. This is "more correct" than what rustc does | |
14 | //! and we are generally migrating in this direction, but NLL had to | |
15 | //! get there first. | |
a1dfa0c6 XL |
16 | //! |
17 | //! Also, this code assumes that there are no bound types at all, not even | |
18 | //! free ones. This is ok because: | |
19 | //! - we are not relating anything quantified over some type variable | |
20 | //! - we will have instantiated all the bound type vars already (the one | |
21 | //! thing we relate in chalk are basically domain goals and their | |
22 | //! constituents) | |
0bf4aa26 | 23 | |
f9f354fc | 24 | use crate::infer::combine::ConstEquateRelation; |
0bf4aa26 | 25 | use crate::infer::InferCtxt; |
dfeec247 | 26 | use crate::infer::{ConstVarValue, ConstVariableValue}; |
0bf4aa26 | 27 | use rustc_data_structures::fx::FxHashMap; |
ba9703b0 XL |
28 | use rustc_middle::ty::error::TypeError; |
29 | use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor}; | |
30 | use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; | |
31 | use rustc_middle::ty::subst::GenericArg; | |
32 | use rustc_middle::ty::{self, InferConst, Ty, TyCtxt}; | |
532ac7d7 | 33 | use std::fmt::Debug; |
0bf4aa26 | 34 | |
e74abb32 | 35 | #[derive(PartialEq)] |
a1dfa0c6 XL |
36 | pub enum NormalizationStrategy { |
37 | Lazy, | |
38 | Eager, | |
39 | } | |
40 | ||
dc9dc135 | 41 | pub struct TypeRelating<'me, 'tcx, D> |
0bf4aa26 XL |
42 | where |
43 | D: TypeRelatingDelegate<'tcx>, | |
44 | { | |
dc9dc135 | 45 | infcx: &'me InferCtxt<'me, 'tcx>, |
0bf4aa26 XL |
46 | |
47 | /// Callback to use when we deduce an outlives relationship | |
48 | delegate: D, | |
49 | ||
50 | /// How are we relating `a` and `b`? | |
51 | /// | |
9fa01778 XL |
52 | /// - Covariant means `a <: b`. |
53 | /// - Contravariant means `b <: a`. | |
54 | /// - Invariant means `a == b. | |
55 | /// - Bivariant means that it doesn't matter. | |
0bf4aa26 XL |
56 | ambient_variance: ty::Variance, |
57 | ||
58 | /// When we pass through a set of binders (e.g., when looking into | |
9fa01778 | 59 | /// a `fn` type), we push a new bound region scope onto here. This |
0bf4aa26 XL |
60 | /// will contain the instantiated region for each region in those |
61 | /// binders. When we then encounter a `ReLateBound(d, br)`, we can | |
9fa01778 | 62 | /// use the De Bruijn index `d` to find the right scope, and then |
0bf4aa26 XL |
63 | /// bound region name `br` to find the specific instantiation from |
64 | /// within that scope. See `replace_bound_region`. | |
65 | /// | |
66 | /// This field stores the instantiations for late-bound regions in | |
67 | /// the `a` type. | |
68 | a_scopes: Vec<BoundRegionScope<'tcx>>, | |
69 | ||
70 | /// Same as `a_scopes`, but for the `b` type. | |
71 | b_scopes: Vec<BoundRegionScope<'tcx>>, | |
72 | } | |
73 | ||
74 | pub trait TypeRelatingDelegate<'tcx> { | |
75 | /// Push a constraint `sup: sub` -- this constraint must be | |
76 | /// satisfied for the two types to be related. `sub` and `sup` may | |
77 | /// be regions from the type or new variables created through the | |
78 | /// delegate. | |
79 | fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>); | |
80 | ||
f9f354fc | 81 | fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>); |
a1dfa0c6 | 82 | |
0bf4aa26 XL |
83 | /// Creates a new universe index. Used when instantiating placeholders. |
84 | fn create_next_universe(&mut self) -> ty::UniverseIndex; | |
85 | ||
86 | /// Creates a new region variable representing a higher-ranked | |
87 | /// region that is instantiated existentially. This creates an | |
88 | /// inference variable, typically. | |
89 | /// | |
0731742a | 90 | /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then |
0bf4aa26 XL |
91 | /// we will invoke this method to instantiate `'a` with an |
92 | /// inference variable (though `'b` would be instantiated first, | |
93 | /// as a placeholder). | |
e74abb32 | 94 | fn next_existential_region_var(&mut self, was_placeholder: bool) -> ty::Region<'tcx>; |
0bf4aa26 XL |
95 | |
96 | /// Creates a new region variable representing a | |
97 | /// higher-ranked region that is instantiated universally. | |
98 | /// This creates a new region placeholder, typically. | |
99 | /// | |
0731742a | 100 | /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then |
0bf4aa26 XL |
101 | /// we will invoke this method to instantiate `'b` with a |
102 | /// placeholder region. | |
a1dfa0c6 | 103 | fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>; |
0bf4aa26 XL |
104 | |
105 | /// Creates a new existential region in the given universe. This | |
106 | /// is used when handling subtyping and type variables -- if we | |
107 | /// have that `?X <: Foo<'a>`, for example, we would instantiate | |
108 | /// `?X` with a type like `Foo<'?0>` where `'?0` is a fresh | |
109 | /// existential variable created by this function. We would then | |
110 | /// relate `Foo<'?0>` with `Foo<'a>` (and probably add an outlives | |
111 | /// relation stating that `'?0: 'a`). | |
112 | fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>; | |
a1dfa0c6 XL |
113 | |
114 | /// Define the normalization strategy to use, eager or lazy. | |
115 | fn normalization() -> NormalizationStrategy; | |
116 | ||
9fa01778 | 117 | /// Enables some optimizations if we do not expect inference variables |
a1dfa0c6 XL |
118 | /// in the RHS of the relation. |
119 | fn forbid_inference_vars() -> bool; | |
0bf4aa26 XL |
120 | } |
121 | ||
122 | #[derive(Clone, Debug)] | |
123 | struct ScopesAndKind<'tcx> { | |
124 | scopes: Vec<BoundRegionScope<'tcx>>, | |
e74abb32 | 125 | kind: GenericArg<'tcx>, |
0bf4aa26 XL |
126 | } |
127 | ||
128 | #[derive(Clone, Debug, Default)] | |
129 | struct BoundRegionScope<'tcx> { | |
130 | map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>, | |
131 | } | |
132 | ||
133 | #[derive(Copy, Clone)] | |
134 | struct UniversallyQuantified(bool); | |
135 | ||
dc9dc135 | 136 | impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D> |
0bf4aa26 XL |
137 | where |
138 | D: TypeRelatingDelegate<'tcx>, | |
139 | { | |
140 | pub fn new( | |
dc9dc135 | 141 | infcx: &'me InferCtxt<'me, 'tcx>, |
0bf4aa26 XL |
142 | delegate: D, |
143 | ambient_variance: ty::Variance, | |
144 | ) -> Self { | |
dfeec247 | 145 | Self { infcx, delegate, ambient_variance, a_scopes: vec![], b_scopes: vec![] } |
0bf4aa26 XL |
146 | } |
147 | ||
148 | fn ambient_covariance(&self) -> bool { | |
149 | match self.ambient_variance { | |
150 | ty::Variance::Covariant | ty::Variance::Invariant => true, | |
151 | ty::Variance::Contravariant | ty::Variance::Bivariant => false, | |
152 | } | |
153 | } | |
154 | ||
155 | fn ambient_contravariance(&self) -> bool { | |
156 | match self.ambient_variance { | |
157 | ty::Variance::Contravariant | ty::Variance::Invariant => true, | |
158 | ty::Variance::Covariant | ty::Variance::Bivariant => false, | |
159 | } | |
160 | } | |
161 | ||
162 | fn create_scope( | |
163 | &mut self, | |
f035d41b | 164 | value: ty::Binder<impl Relate<'tcx>>, |
0bf4aa26 XL |
165 | universally_quantified: UniversallyQuantified, |
166 | ) -> BoundRegionScope<'tcx> { | |
167 | let mut scope = BoundRegionScope::default(); | |
168 | ||
169 | // Create a callback that creates (via the delegate) either an | |
170 | // existential or placeholder region as needed. | |
171 | let mut next_region = { | |
172 | let delegate = &mut self.delegate; | |
173 | let mut lazy_universe = None; | |
174 | move |br: ty::BoundRegion| { | |
175 | if universally_quantified.0 { | |
176 | // The first time this closure is called, create a | |
177 | // new universe for the placeholders we will make | |
178 | // from here out. | |
179 | let universe = lazy_universe.unwrap_or_else(|| { | |
180 | let universe = delegate.create_next_universe(); | |
181 | lazy_universe = Some(universe); | |
182 | universe | |
183 | }); | |
184 | ||
a1dfa0c6 | 185 | let placeholder = ty::PlaceholderRegion { universe, name: br }; |
0bf4aa26 XL |
186 | delegate.next_placeholder_region(placeholder) |
187 | } else { | |
e74abb32 | 188 | delegate.next_existential_region_var(true) |
0bf4aa26 XL |
189 | } |
190 | } | |
191 | }; | |
192 | ||
193 | value.skip_binder().visit_with(&mut ScopeInstantiator { | |
194 | next_region: &mut next_region, | |
195 | target_index: ty::INNERMOST, | |
196 | bound_region_scope: &mut scope, | |
197 | }); | |
198 | ||
199 | scope | |
200 | } | |
201 | ||
202 | /// When we encounter binders during the type traversal, we record | |
203 | /// the value to substitute for each of the things contained in | |
204 | /// that binder. (This will be either a universal placeholder or | |
9fa01778 | 205 | /// an existential inference variable.) Given the De Bruijn index |
0bf4aa26 XL |
206 | /// `debruijn` (and name `br`) of some binder we have now |
207 | /// encountered, this routine finds the value that we instantiated | |
208 | /// the region with; to do so, it indexes backwards into the list | |
209 | /// of ambient scopes `scopes`. | |
210 | fn lookup_bound_region( | |
211 | debruijn: ty::DebruijnIndex, | |
212 | br: &ty::BoundRegion, | |
213 | first_free_index: ty::DebruijnIndex, | |
214 | scopes: &[BoundRegionScope<'tcx>], | |
215 | ) -> ty::Region<'tcx> { | |
216 | // The debruijn index is a "reverse index" into the | |
217 | // scopes listing. So when we have INNERMOST (0), we | |
218 | // want the *last* scope pushed, and so forth. | |
219 | let debruijn_index = debruijn.index() - first_free_index.index(); | |
220 | let scope = &scopes[scopes.len() - debruijn_index - 1]; | |
221 | ||
222 | // Find this bound region in that scope to map to a | |
223 | // particular region. | |
224 | scope.map[br] | |
225 | } | |
226 | ||
227 | /// If `r` is a bound region, find the scope in which it is bound | |
228 | /// (from `scopes`) and return the value that we instantiated it | |
229 | /// with. Otherwise just return `r`. | |
230 | fn replace_bound_region( | |
231 | &self, | |
232 | r: ty::Region<'tcx>, | |
233 | first_free_index: ty::DebruijnIndex, | |
234 | scopes: &[BoundRegionScope<'tcx>], | |
235 | ) -> ty::Region<'tcx> { | |
532ac7d7 | 236 | debug!("replace_bound_regions(scopes={:?})", scopes); |
0bf4aa26 XL |
237 | if let ty::ReLateBound(debruijn, br) = r { |
238 | Self::lookup_bound_region(*debruijn, br, first_free_index, scopes) | |
239 | } else { | |
240 | r | |
241 | } | |
242 | } | |
243 | ||
244 | /// Push a new outlives requirement into our output set of | |
245 | /// constraints. | |
246 | fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) { | |
247 | debug!("push_outlives({:?}: {:?})", sup, sub); | |
248 | ||
249 | self.delegate.push_outlives(sup, sub); | |
250 | } | |
251 | ||
a1dfa0c6 XL |
252 | /// Relate a projection type and some value type lazily. This will always |
253 | /// succeed, but we push an additional `ProjectionEq` goal depending | |
254 | /// on the value type: | |
255 | /// - if the value type is any type `T` which is not a projection, we push | |
256 | /// `ProjectionEq(projection = T)`. | |
257 | /// - if the value type is another projection `other_projection`, we create | |
258 | /// a new inference variable `?U` and push the two goals | |
259 | /// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`. | |
260 | fn relate_projection_ty( | |
261 | &mut self, | |
262 | projection_ty: ty::ProjectionTy<'tcx>, | |
48663c56 | 263 | value_ty: Ty<'tcx>, |
a1dfa0c6 | 264 | ) -> Ty<'tcx> { |
dc9dc135 | 265 | use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; |
dfeec247 | 266 | use rustc_span::DUMMY_SP; |
a1dfa0c6 | 267 | |
e74abb32 | 268 | match value_ty.kind { |
a1dfa0c6 | 269 | ty::Projection(other_projection_ty) => { |
dc9dc135 XL |
270 | let var = self.infcx.next_ty_var(TypeVariableOrigin { |
271 | kind: TypeVariableOriginKind::MiscVariable, | |
272 | span: DUMMY_SP, | |
273 | }); | |
a1dfa0c6 XL |
274 | self.relate_projection_ty(projection_ty, var); |
275 | self.relate_projection_ty(other_projection_ty, var); | |
276 | var | |
277 | } | |
278 | ||
f9f354fc | 279 | _ => bug!("should never be invoked with eager normalization"), |
a1dfa0c6 XL |
280 | } |
281 | } | |
282 | ||
532ac7d7 XL |
283 | /// Relate a type inference variable with a value type. This works |
284 | /// by creating a "generalization" G of the value where all the | |
285 | /// lifetimes are replaced with fresh inference values. This | |
286 | /// genearlization G becomes the value of the inference variable, | |
287 | /// and is then related in turn to the value. So e.g. if you had | |
288 | /// `vid = ?0` and `value = &'a u32`, we might first instantiate | |
289 | /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable, | |
290 | /// and then relate `&'0 u32` with `&'a u32` (resulting in | |
291 | /// relations between `'0` and `'a`). | |
292 | /// | |
293 | /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)` | |
294 | /// -- in other words, it is always a (unresolved) inference | |
295 | /// variable `vid` and a type `ty` that are being related, but the | |
296 | /// vid may appear either as the "a" type or the "b" type, | |
297 | /// depending on where it appears in the tuple. The trait | |
298 | /// `VidValuePair` lets us work with the vid/type while preserving | |
299 | /// the "sidedness" when necessary -- the sidedness is relevant in | |
300 | /// particular for the variance and set of in-scope things. | |
301 | fn relate_ty_var<PAIR: VidValuePair<'tcx>>( | |
a1dfa0c6 | 302 | &mut self, |
532ac7d7 | 303 | pair: PAIR, |
a1dfa0c6 | 304 | ) -> RelateResult<'tcx, Ty<'tcx>> { |
532ac7d7 | 305 | debug!("relate_ty_var({:?})", pair); |
a1dfa0c6 | 306 | |
532ac7d7 XL |
307 | let vid = pair.vid(); |
308 | let value_ty = pair.value_ty(); | |
309 | ||
e74abb32 | 310 | // FIXME(invariance) -- this logic assumes invariance, but that is wrong. |
532ac7d7 XL |
311 | // This only presently applies to chalk integration, as NLL |
312 | // doesn't permit type variables to appear on both sides (and | |
313 | // doesn't use lazy norm). | |
e74abb32 | 314 | match value_ty.kind { |
a1dfa0c6 XL |
315 | ty::Infer(ty::TyVar(value_vid)) => { |
316 | // Two type variables: just equate them. | |
f9f354fc | 317 | self.infcx.inner.borrow_mut().type_variables().equate(vid, value_vid); |
a1dfa0c6 XL |
318 | return Ok(value_ty); |
319 | } | |
320 | ||
532ac7d7 XL |
321 | ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => { |
322 | return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid))); | |
a1dfa0c6 XL |
323 | } |
324 | ||
325 | _ => (), | |
326 | } | |
327 | ||
328 | let generalized_ty = self.generalize_value(value_ty, vid)?; | |
329 | debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty); | |
330 | ||
331 | if D::forbid_inference_vars() { | |
332 | // In NLL, we don't have type inference variables | |
333 | // floating around, so we can do this rather imprecise | |
334 | // variant of the occurs-check. | |
74b04a01 | 335 | assert!(!generalized_ty.has_infer_types_or_consts()); |
a1dfa0c6 | 336 | } |
0bf4aa26 | 337 | |
f9f354fc | 338 | self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty); |
0bf4aa26 XL |
339 | |
340 | // The generalized values we extract from `canonical_var_values` have | |
341 | // been fully instantiated and hence the set of scopes we have | |
342 | // doesn't matter -- just to be sure, put an empty vector | |
343 | // in there. | |
416331ca | 344 | let old_a_scopes = ::std::mem::take(pair.vid_scopes(self)); |
0bf4aa26 XL |
345 | |
346 | // Relate the generalized kind to the original one. | |
532ac7d7 | 347 | let result = pair.relate_generalized_ty(self, generalized_ty); |
0bf4aa26 XL |
348 | |
349 | // Restore the old scopes now. | |
532ac7d7 | 350 | *pair.vid_scopes(self) = old_a_scopes; |
0bf4aa26 | 351 | |
a1dfa0c6 | 352 | debug!("relate_ty_var: complete, result = {:?}", result); |
0bf4aa26 XL |
353 | result |
354 | } | |
355 | ||
a1dfa0c6 XL |
356 | fn generalize_value<T: Relate<'tcx>>( |
357 | &mut self, | |
358 | value: T, | |
532ac7d7 | 359 | for_vid: ty::TyVid, |
a1dfa0c6 XL |
360 | ) -> RelateResult<'tcx, T> { |
361 | let universe = self.infcx.probe_ty_var(for_vid).unwrap_err(); | |
362 | ||
363 | let mut generalizer = TypeGeneralizer { | |
364 | infcx: self.infcx, | |
0bf4aa26 XL |
365 | delegate: &mut self.delegate, |
366 | first_free_index: ty::INNERMOST, | |
367 | ambient_variance: self.ambient_variance, | |
f9f354fc | 368 | for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid), |
a1dfa0c6 XL |
369 | universe, |
370 | }; | |
0bf4aa26 | 371 | |
f035d41b | 372 | generalizer.relate(value, value) |
0bf4aa26 XL |
373 | } |
374 | } | |
375 | ||
532ac7d7 XL |
376 | /// When we instantiate a inference variable with a value in |
377 | /// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`, | |
378 | /// but the ordering may vary (depending on whether the inference | |
379 | /// variable was found on the `a` or `b` sides). Therefore, this trait | |
380 | /// allows us to factor out common code, while preserving the order | |
381 | /// when needed. | |
382 | trait VidValuePair<'tcx>: Debug { | |
383 | /// Extract the inference variable (which could be either the | |
384 | /// first or second part of the tuple). | |
385 | fn vid(&self) -> ty::TyVid; | |
386 | ||
387 | /// Extract the value it is being related to (which will be the | |
388 | /// opposite part of the tuple from the vid). | |
389 | fn value_ty(&self) -> Ty<'tcx>; | |
390 | ||
391 | /// Extract the scopes that apply to whichever side of the tuple | |
392 | /// the vid was found on. See the comment where this is called | |
393 | /// for more details on why we want them. | |
394 | fn vid_scopes<D: TypeRelatingDelegate<'tcx>>( | |
395 | &self, | |
dc9dc135 | 396 | relate: &'r mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
397 | ) -> &'r mut Vec<BoundRegionScope<'tcx>>; |
398 | ||
399 | /// Given a generalized type G that should replace the vid, relate | |
400 | /// G to the value, putting G on whichever side the vid would have | |
401 | /// appeared. | |
402 | fn relate_generalized_ty<D>( | |
403 | &self, | |
dc9dc135 | 404 | relate: &mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
405 | generalized_ty: Ty<'tcx>, |
406 | ) -> RelateResult<'tcx, Ty<'tcx>> | |
407 | where | |
408 | D: TypeRelatingDelegate<'tcx>; | |
409 | } | |
410 | ||
411 | impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) { | |
412 | fn vid(&self) -> ty::TyVid { | |
413 | self.0 | |
414 | } | |
415 | ||
416 | fn value_ty(&self) -> Ty<'tcx> { | |
417 | self.1 | |
418 | } | |
419 | ||
420 | fn vid_scopes<D>( | |
421 | &self, | |
dc9dc135 | 422 | relate: &'r mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
423 | ) -> &'r mut Vec<BoundRegionScope<'tcx>> |
424 | where | |
425 | D: TypeRelatingDelegate<'tcx>, | |
426 | { | |
427 | &mut relate.a_scopes | |
428 | } | |
429 | ||
430 | fn relate_generalized_ty<D>( | |
431 | &self, | |
dc9dc135 | 432 | relate: &mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
433 | generalized_ty: Ty<'tcx>, |
434 | ) -> RelateResult<'tcx, Ty<'tcx>> | |
435 | where | |
436 | D: TypeRelatingDelegate<'tcx>, | |
437 | { | |
438 | relate.relate(&generalized_ty, &self.value_ty()) | |
439 | } | |
440 | } | |
441 | ||
442 | // In this case, the "vid" is the "b" type. | |
443 | impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) { | |
444 | fn vid(&self) -> ty::TyVid { | |
445 | self.1 | |
446 | } | |
447 | ||
448 | fn value_ty(&self) -> Ty<'tcx> { | |
449 | self.0 | |
450 | } | |
451 | ||
452 | fn vid_scopes<D>( | |
453 | &self, | |
dc9dc135 | 454 | relate: &'r mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
455 | ) -> &'r mut Vec<BoundRegionScope<'tcx>> |
456 | where | |
457 | D: TypeRelatingDelegate<'tcx>, | |
458 | { | |
459 | &mut relate.b_scopes | |
460 | } | |
461 | ||
462 | fn relate_generalized_ty<D>( | |
463 | &self, | |
dc9dc135 | 464 | relate: &mut TypeRelating<'_, 'tcx, D>, |
532ac7d7 XL |
465 | generalized_ty: Ty<'tcx>, |
466 | ) -> RelateResult<'tcx, Ty<'tcx>> | |
467 | where | |
468 | D: TypeRelatingDelegate<'tcx>, | |
469 | { | |
470 | relate.relate(&self.value_ty(), &generalized_ty) | |
471 | } | |
472 | } | |
473 | ||
dc9dc135 | 474 | impl<D> TypeRelation<'tcx> for TypeRelating<'me, 'tcx, D> |
0bf4aa26 XL |
475 | where |
476 | D: TypeRelatingDelegate<'tcx>, | |
477 | { | |
dc9dc135 | 478 | fn tcx(&self) -> TyCtxt<'tcx> { |
0bf4aa26 XL |
479 | self.infcx.tcx |
480 | } | |
481 | ||
416331ca | 482 | // FIXME(oli-obk): not sure how to get the correct ParamEnv |
dfeec247 XL |
483 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
484 | ty::ParamEnv::empty() | |
485 | } | |
416331ca | 486 | |
0bf4aa26 XL |
487 | fn tag(&self) -> &'static str { |
488 | "nll::subtype" | |
489 | } | |
490 | ||
491 | fn a_is_expected(&self) -> bool { | |
492 | true | |
493 | } | |
494 | ||
495 | fn relate_with_variance<T: Relate<'tcx>>( | |
496 | &mut self, | |
497 | variance: ty::Variance, | |
f035d41b XL |
498 | a: T, |
499 | b: T, | |
0bf4aa26 | 500 | ) -> RelateResult<'tcx, T> { |
dfeec247 | 501 | debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b); |
0bf4aa26 XL |
502 | |
503 | let old_ambient_variance = self.ambient_variance; | |
504 | self.ambient_variance = self.ambient_variance.xform(variance); | |
505 | ||
dfeec247 | 506 | debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance); |
0bf4aa26 XL |
507 | |
508 | let r = self.relate(a, b)?; | |
509 | ||
510 | self.ambient_variance = old_ambient_variance; | |
511 | ||
512 | debug!("relate_with_variance: r={:?}", r); | |
513 | ||
514 | Ok(r) | |
515 | } | |
516 | ||
a1dfa0c6 | 517 | fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { |
0bf4aa26 | 518 | let a = self.infcx.shallow_resolve(a); |
a1dfa0c6 XL |
519 | |
520 | if !D::forbid_inference_vars() { | |
521 | b = self.infcx.shallow_resolve(b); | |
522 | } | |
523 | ||
74b04a01 | 524 | if a == b { |
f035d41b XL |
525 | // Subtle: if a or b has a bound variable that we are lazilly |
526 | // substituting, then even if a == b, it could be that the values we | |
527 | // will substitute for those bound variables are *not* the same, and | |
528 | // hence returning `Ok(a)` is incorrect. | |
529 | if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() { | |
530 | return Ok(a); | |
531 | } | |
74b04a01 XL |
532 | } |
533 | ||
e74abb32 | 534 | match (&a.kind, &b.kind) { |
a1dfa0c6 XL |
535 | (_, &ty::Infer(ty::TyVar(vid))) => { |
536 | if D::forbid_inference_vars() { | |
537 | // Forbid inference variables in the RHS. | |
538 | bug!("unexpected inference var {:?}", b) | |
539 | } else { | |
532ac7d7 | 540 | self.relate_ty_var((a, vid)) |
a1dfa0c6 XL |
541 | } |
542 | } | |
543 | ||
532ac7d7 | 544 | (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)), |
a1dfa0c6 XL |
545 | |
546 | (&ty::Projection(projection_ty), _) | |
547 | if D::normalization() == NormalizationStrategy::Lazy => | |
548 | { | |
549 | Ok(self.relate_projection_ty(projection_ty, b)) | |
550 | } | |
551 | ||
552 | (_, &ty::Projection(projection_ty)) | |
553 | if D::normalization() == NormalizationStrategy::Lazy => | |
554 | { | |
555 | Ok(self.relate_projection_ty(projection_ty, a)) | |
0bf4aa26 XL |
556 | } |
557 | ||
558 | _ => { | |
dfeec247 | 559 | debug!("tys(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); |
0bf4aa26 | 560 | |
a1dfa0c6 XL |
561 | // Will also handle unification of `IntVar` and `FloatVar`. |
562 | self.infcx.super_combine_tys(self, a, b) | |
0bf4aa26 XL |
563 | } |
564 | } | |
565 | } | |
566 | ||
567 | fn regions( | |
568 | &mut self, | |
569 | a: ty::Region<'tcx>, | |
570 | b: ty::Region<'tcx>, | |
571 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
dfeec247 | 572 | debug!("regions(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance); |
0bf4aa26 XL |
573 | |
574 | let v_a = self.replace_bound_region(a, ty::INNERMOST, &self.a_scopes); | |
575 | let v_b = self.replace_bound_region(b, ty::INNERMOST, &self.b_scopes); | |
576 | ||
577 | debug!("regions: v_a = {:?}", v_a); | |
578 | debug!("regions: v_b = {:?}", v_b); | |
579 | ||
580 | if self.ambient_covariance() { | |
581 | // Covariance: a <= b. Hence, `b: a`. | |
582 | self.push_outlives(v_b, v_a); | |
583 | } | |
584 | ||
585 | if self.ambient_contravariance() { | |
586 | // Contravariant: b <= a. Hence, `a: b`. | |
587 | self.push_outlives(v_a, v_b); | |
588 | } | |
589 | ||
590 | Ok(a) | |
591 | } | |
592 | ||
48663c56 XL |
593 | fn consts( |
594 | &mut self, | |
595 | a: &'tcx ty::Const<'tcx>, | |
e74abb32 | 596 | mut b: &'tcx ty::Const<'tcx>, |
48663c56 | 597 | ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { |
e74abb32 XL |
598 | let a = self.infcx.shallow_resolve(a); |
599 | ||
600 | if !D::forbid_inference_vars() { | |
601 | b = self.infcx.shallow_resolve(b); | |
602 | } | |
603 | ||
604 | match b.val { | |
60c5eb7d | 605 | ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { |
e74abb32 XL |
606 | // Forbid inference variables in the RHS. |
607 | bug!("unexpected inference var {:?}", b) | |
608 | } | |
609 | // FIXME(invariance): see the related FIXME above. | |
dfeec247 | 610 | _ => self.infcx.super_combine_consts(self, a, b), |
48663c56 XL |
611 | } |
612 | } | |
613 | ||
0bf4aa26 XL |
614 | fn binders<T>( |
615 | &mut self, | |
f035d41b XL |
616 | a: ty::Binder<T>, |
617 | b: ty::Binder<T>, | |
0bf4aa26 XL |
618 | ) -> RelateResult<'tcx, ty::Binder<T>> |
619 | where | |
620 | T: Relate<'tcx>, | |
621 | { | |
622 | // We want that | |
623 | // | |
624 | // ``` | |
625 | // for<'a> fn(&'a u32) -> &'a u32 <: | |
626 | // fn(&'b u32) -> &'b u32 | |
627 | // ``` | |
628 | // | |
629 | // but not | |
630 | // | |
631 | // ``` | |
632 | // fn(&'a u32) -> &'a u32 <: | |
633 | // for<'b> fn(&'b u32) -> &'b u32 | |
634 | // ``` | |
635 | // | |
636 | // We therefore proceed as follows: | |
637 | // | |
638 | // - Instantiate binders on `b` universally, yielding a universe U1. | |
639 | // - Instantiate binders on `a` existentially in U1. | |
640 | ||
dfeec247 | 641 | debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance); |
0bf4aa26 | 642 | |
f035d41b | 643 | if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) { |
74b04a01 | 644 | // Fast path for the common case. |
f035d41b XL |
645 | self.relate(a, b)?; |
646 | return Ok(ty::Binder::bind(a)); | |
74b04a01 XL |
647 | } |
648 | ||
0bf4aa26 XL |
649 | if self.ambient_covariance() { |
650 | // Covariance, so we want `for<..> A <: for<..> B` -- | |
651 | // therefore we compare any instantiation of A (i.e., A | |
652 | // instantiated with existentials) against every | |
653 | // instantiation of B (i.e., B instantiated with | |
654 | // universals). | |
655 | ||
656 | let b_scope = self.create_scope(b, UniversallyQuantified(true)); | |
657 | let a_scope = self.create_scope(a, UniversallyQuantified(false)); | |
658 | ||
659 | debug!("binders: a_scope = {:?} (existential)", a_scope); | |
660 | debug!("binders: b_scope = {:?} (universal)", b_scope); | |
661 | ||
662 | self.b_scopes.push(b_scope); | |
663 | self.a_scopes.push(a_scope); | |
664 | ||
665 | // Reset the ambient variance to covariant. This is needed | |
666 | // to correctly handle cases like | |
667 | // | |
f9f354fc | 668 | // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32) |
0bf4aa26 XL |
669 | // |
670 | // Somewhat surprisingly, these two types are actually | |
671 | // **equal**, even though the one on the right looks more | |
672 | // polymorphic. The reason is due to subtyping. To see it, | |
673 | // consider that each function can call the other: | |
674 | // | |
675 | // - The left function can call the right with `'b` and | |
676 | // `'c` both equal to `'a` | |
677 | // | |
678 | // - The right function can call the left with `'a` set to | |
679 | // `{P}`, where P is the point in the CFG where the call | |
680 | // itself occurs. Note that `'b` and `'c` must both | |
681 | // include P. At the point, the call works because of | |
682 | // subtyping (i.e., `&'b u32 <: &{P} u32`). | |
683 | let variance = ::std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant); | |
684 | ||
685 | self.relate(a.skip_binder(), b.skip_binder())?; | |
686 | ||
687 | self.ambient_variance = variance; | |
688 | ||
689 | self.b_scopes.pop().unwrap(); | |
690 | self.a_scopes.pop().unwrap(); | |
691 | } | |
692 | ||
693 | if self.ambient_contravariance() { | |
694 | // Contravariance, so we want `for<..> A :> for<..> B` | |
695 | // -- therefore we compare every instantiation of A (i.e., | |
696 | // A instantiated with universals) against any | |
697 | // instantiation of B (i.e., B instantiated with | |
698 | // existentials). Opposite of above. | |
699 | ||
700 | let a_scope = self.create_scope(a, UniversallyQuantified(true)); | |
701 | let b_scope = self.create_scope(b, UniversallyQuantified(false)); | |
702 | ||
703 | debug!("binders: a_scope = {:?} (universal)", a_scope); | |
704 | debug!("binders: b_scope = {:?} (existential)", b_scope); | |
705 | ||
706 | self.a_scopes.push(a_scope); | |
707 | self.b_scopes.push(b_scope); | |
708 | ||
709 | // Reset ambient variance to contravariance. See the | |
710 | // covariant case above for an explanation. | |
711 | let variance = | |
712 | ::std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant); | |
713 | ||
714 | self.relate(a.skip_binder(), b.skip_binder())?; | |
715 | ||
716 | self.ambient_variance = variance; | |
717 | ||
718 | self.b_scopes.pop().unwrap(); | |
719 | self.a_scopes.pop().unwrap(); | |
720 | } | |
721 | ||
3dfed10e | 722 | Ok(a) |
0bf4aa26 XL |
723 | } |
724 | } | |
725 | ||
f9f354fc XL |
726 | impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D> |
727 | where | |
728 | D: TypeRelatingDelegate<'tcx>, | |
729 | { | |
730 | fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) { | |
731 | self.delegate.const_equate(a, b); | |
732 | } | |
733 | } | |
734 | ||
0bf4aa26 XL |
735 | /// When we encounter a binder like `for<..> fn(..)`, we actually have |
736 | /// to walk the `fn` value to find all the values bound by the `for` | |
737 | /// (these are not explicitly present in the ty representation right | |
738 | /// now). This visitor handles that: it descends the type, tracking | |
739 | /// binder depth, and finds late-bound regions targeting the | |
740 | /// `for<..`>. For each of those, it creates an entry in | |
741 | /// `bound_region_scope`. | |
dc9dc135 | 742 | struct ScopeInstantiator<'me, 'tcx> { |
0bf4aa26 XL |
743 | next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>, |
744 | // The debruijn index of the scope we are instantiating. | |
745 | target_index: ty::DebruijnIndex, | |
746 | bound_region_scope: &'me mut BoundRegionScope<'tcx>, | |
747 | } | |
748 | ||
749 | impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> { | |
750 | fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool { | |
751 | self.target_index.shift_in(1); | |
752 | t.super_visit_with(self); | |
753 | self.target_index.shift_out(1); | |
754 | ||
755 | false | |
756 | } | |
757 | ||
758 | fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { | |
dfeec247 | 759 | let ScopeInstantiator { bound_region_scope, next_region, .. } = self; |
0bf4aa26 XL |
760 | |
761 | match r { | |
762 | ty::ReLateBound(debruijn, br) if *debruijn == self.target_index => { | |
dfeec247 | 763 | bound_region_scope.map.entry(*br).or_insert_with(|| next_region(*br)); |
0bf4aa26 XL |
764 | } |
765 | ||
766 | _ => {} | |
767 | } | |
768 | ||
769 | false | |
770 | } | |
771 | } | |
772 | ||
773 | /// The "type generalize" is used when handling inference variables. | |
774 | /// | |
775 | /// The basic strategy for handling a constraint like `?A <: B` is to | |
776 | /// apply a "generalization strategy" to the type `B` -- this replaces | |
777 | /// all the lifetimes in the type `B` with fresh inference | |
778 | /// variables. (You can read more about the strategy in this [blog | |
779 | /// post].) | |
780 | /// | |
781 | /// As an example, if we had `?A <: &'x u32`, we would generalize `&'x | |
782 | /// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the | |
783 | /// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which | |
784 | /// establishes `'0: 'x` as a constraint. | |
785 | /// | |
786 | /// As a side-effect of this generalization procedure, we also replace | |
787 | /// all the bound regions that we have traversed with concrete values, | |
788 | /// so that the resulting generalized type is independent from the | |
789 | /// scopes. | |
790 | /// | |
791 | /// [blog post]: https://is.gd/0hKvIr | |
dc9dc135 | 792 | struct TypeGeneralizer<'me, 'tcx, D> |
0bf4aa26 | 793 | where |
dc9dc135 | 794 | D: TypeRelatingDelegate<'tcx>, |
0bf4aa26 | 795 | { |
dc9dc135 | 796 | infcx: &'me InferCtxt<'me, 'tcx>, |
0bf4aa26 XL |
797 | |
798 | delegate: &'me mut D, | |
799 | ||
800 | /// After we generalize this type, we are going to relative it to | |
801 | /// some other type. What will be the variance at this point? | |
802 | ambient_variance: ty::Variance, | |
803 | ||
804 | first_free_index: ty::DebruijnIndex, | |
805 | ||
a1dfa0c6 XL |
806 | /// The vid of the type variable that is in the process of being |
807 | /// instantiated. If we find this within the value we are folding, | |
808 | /// that means we would have created a cyclic value. | |
809 | for_vid_sub_root: ty::TyVid, | |
810 | ||
811 | /// The universe of the type variable that is in the process of being | |
812 | /// instantiated. If we find anything that this universe cannot name, | |
813 | /// we reject the relation. | |
0bf4aa26 XL |
814 | universe: ty::UniverseIndex, |
815 | } | |
816 | ||
dc9dc135 | 817 | impl<D> TypeRelation<'tcx> for TypeGeneralizer<'me, 'tcx, D> |
0bf4aa26 XL |
818 | where |
819 | D: TypeRelatingDelegate<'tcx>, | |
820 | { | |
dc9dc135 | 821 | fn tcx(&self) -> TyCtxt<'tcx> { |
a1dfa0c6 | 822 | self.infcx.tcx |
0bf4aa26 XL |
823 | } |
824 | ||
416331ca | 825 | // FIXME(oli-obk): not sure how to get the correct ParamEnv |
dfeec247 XL |
826 | fn param_env(&self) -> ty::ParamEnv<'tcx> { |
827 | ty::ParamEnv::empty() | |
828 | } | |
416331ca | 829 | |
0bf4aa26 XL |
830 | fn tag(&self) -> &'static str { |
831 | "nll::generalizer" | |
832 | } | |
833 | ||
834 | fn a_is_expected(&self) -> bool { | |
835 | true | |
836 | } | |
837 | ||
838 | fn relate_with_variance<T: Relate<'tcx>>( | |
839 | &mut self, | |
840 | variance: ty::Variance, | |
f035d41b XL |
841 | a: T, |
842 | b: T, | |
0bf4aa26 XL |
843 | ) -> RelateResult<'tcx, T> { |
844 | debug!( | |
845 | "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})", | |
846 | variance, a, b | |
847 | ); | |
848 | ||
849 | let old_ambient_variance = self.ambient_variance; | |
850 | self.ambient_variance = self.ambient_variance.xform(variance); | |
851 | ||
852 | debug!( | |
853 | "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}", | |
854 | self.ambient_variance | |
855 | ); | |
856 | ||
857 | let r = self.relate(a, b)?; | |
858 | ||
859 | self.ambient_variance = old_ambient_variance; | |
860 | ||
861 | debug!("TypeGeneralizer::relate_with_variance: r={:?}", r); | |
862 | ||
863 | Ok(r) | |
864 | } | |
865 | ||
866 | fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { | |
a1dfa0c6 XL |
867 | use crate::infer::type_variable::TypeVariableValue; |
868 | ||
48663c56 | 869 | debug!("TypeGeneralizer::tys(a={:?})", a); |
0bf4aa26 | 870 | |
e74abb32 | 871 | match a.kind { |
a1dfa0c6 XL |
872 | ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
873 | if D::forbid_inference_vars() => | |
874 | { | |
dfeec247 | 875 | bug!("unexpected inference variable encountered in NLL generalization: {:?}", a); |
0bf4aa26 XL |
876 | } |
877 | ||
a1dfa0c6 | 878 | ty::Infer(ty::TyVar(vid)) => { |
f9f354fc XL |
879 | let mut inner = self.infcx.inner.borrow_mut(); |
880 | let variables = &mut inner.type_variables(); | |
a1dfa0c6 XL |
881 | let vid = variables.root_var(vid); |
882 | let sub_vid = variables.sub_root_var(vid); | |
883 | if sub_vid == self.for_vid_sub_root { | |
884 | // If sub-roots are equal, then `for_vid` and | |
885 | // `vid` are related via subtyping. | |
886 | debug!("TypeGeneralizer::tys: occurs check failed"); | |
ba9703b0 | 887 | Err(TypeError::Mismatch) |
a1dfa0c6 XL |
888 | } else { |
889 | match variables.probe(vid) { | |
890 | TypeVariableValue::Known { value: u } => { | |
891 | drop(variables); | |
f035d41b | 892 | self.relate(u, u) |
a1dfa0c6 | 893 | } |
dfeec247 | 894 | TypeVariableValue::Unknown { universe: _universe } => { |
a1dfa0c6 XL |
895 | if self.ambient_variance == ty::Bivariant { |
896 | // FIXME: we may need a WF predicate (related to #54105). | |
897 | } | |
898 | ||
899 | let origin = *variables.var_origin(vid); | |
900 | ||
901 | // Replacing with a new variable in the universe `self.universe`, | |
902 | // it will be unified later with the original type variable in | |
903 | // the universe `_universe`. | |
904 | let new_var_id = variables.new_var(self.universe, false, origin); | |
905 | ||
532ac7d7 | 906 | let u = self.tcx().mk_ty_var(new_var_id); |
dfeec247 | 907 | debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); |
ba9703b0 | 908 | Ok(u) |
a1dfa0c6 XL |
909 | } |
910 | } | |
911 | } | |
912 | } | |
913 | ||
ba9703b0 | 914 | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => { |
a1dfa0c6 XL |
915 | // No matter what mode we are in, |
916 | // integer/floating-point types must be equal to be | |
917 | // relatable. | |
918 | Ok(a) | |
919 | } | |
920 | ||
921 | ty::Placeholder(placeholder) => { | |
922 | if self.universe.cannot_name(placeholder.universe) { | |
923 | debug!( | |
924 | "TypeGeneralizer::tys: root universe {:?} cannot name\ | |
532ac7d7 XL |
925 | placeholder in universe {:?}", |
926 | self.universe, placeholder.universe | |
a1dfa0c6 XL |
927 | ); |
928 | Err(TypeError::Mismatch) | |
929 | } else { | |
930 | Ok(a) | |
931 | } | |
932 | } | |
933 | ||
532ac7d7 | 934 | _ => relate::super_relate_tys(self, a, a), |
0bf4aa26 XL |
935 | } |
936 | } | |
937 | ||
938 | fn regions( | |
939 | &mut self, | |
940 | a: ty::Region<'tcx>, | |
941 | _: ty::Region<'tcx>, | |
942 | ) -> RelateResult<'tcx, ty::Region<'tcx>> { | |
48663c56 | 943 | debug!("TypeGeneralizer::regions(a={:?})", a); |
0bf4aa26 XL |
944 | |
945 | if let ty::ReLateBound(debruijn, _) = a { | |
946 | if *debruijn < self.first_free_index { | |
947 | return Ok(a); | |
948 | } | |
949 | } | |
950 | ||
951 | // For now, we just always create a fresh region variable to | |
952 | // replace all the regions in the source type. In the main | |
953 | // type checker, we special case the case where the ambient | |
954 | // variance is `Invariant` and try to avoid creating a fresh | |
955 | // region variable, but since this comes up so much less in | |
956 | // NLL (only when users use `_` etc) it is much less | |
957 | // important. | |
958 | // | |
959 | // As an aside, since these new variables are created in | |
960 | // `self.universe` universe, this also serves to enforce the | |
961 | // universe scoping rules. | |
962 | // | |
963 | // FIXME(#54105) -- if the ambient variance is bivariant, | |
964 | // though, we may however need to check well-formedness or | |
965 | // risk a problem like #41677 again. | |
966 | ||
967 | let replacement_region_vid = self.delegate.generalize_existential(self.universe); | |
968 | ||
969 | Ok(replacement_region_vid) | |
970 | } | |
971 | ||
48663c56 XL |
972 | fn consts( |
973 | &mut self, | |
974 | a: &'tcx ty::Const<'tcx>, | |
975 | _: &'tcx ty::Const<'tcx>, | |
976 | ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { | |
e74abb32 | 977 | match a.val { |
60c5eb7d | 978 | ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => { |
dfeec247 | 979 | bug!("unexpected inference variable encountered in NLL generalization: {:?}", a); |
e74abb32 | 980 | } |
60c5eb7d | 981 | ty::ConstKind::Infer(InferConst::Var(vid)) => { |
f9f354fc XL |
982 | let mut inner = self.infcx.inner.borrow_mut(); |
983 | let variable_table = &mut inner.const_unification_table(); | |
e74abb32 XL |
984 | let var_value = variable_table.probe_value(vid); |
985 | match var_value.val.known() { | |
f035d41b | 986 | Some(u) => self.relate(u, u), |
e74abb32 XL |
987 | None => { |
988 | let new_var_id = variable_table.new_key(ConstVarValue { | |
989 | origin: var_value.origin, | |
990 | val: ConstVariableValue::Unknown { universe: self.universe }, | |
991 | }); | |
992 | Ok(self.tcx().mk_const_var(new_var_id, a.ty)) | |
993 | } | |
994 | } | |
995 | } | |
f9f354fc | 996 | ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a), |
e74abb32 | 997 | _ => relate::super_relate_consts(self, a, a), |
48663c56 XL |
998 | } |
999 | } | |
1000 | ||
0bf4aa26 XL |
1001 | fn binders<T>( |
1002 | &mut self, | |
f035d41b XL |
1003 | a: ty::Binder<T>, |
1004 | _: ty::Binder<T>, | |
0bf4aa26 XL |
1005 | ) -> RelateResult<'tcx, ty::Binder<T>> |
1006 | where | |
1007 | T: Relate<'tcx>, | |
1008 | { | |
48663c56 | 1009 | debug!("TypeGeneralizer::binders(a={:?})", a); |
0bf4aa26 XL |
1010 | |
1011 | self.first_free_index.shift_in(1); | |
1012 | let result = self.relate(a.skip_binder(), a.skip_binder())?; | |
1013 | self.first_free_index.shift_out(1); | |
1014 | Ok(ty::Binder::bind(result)) | |
1015 | } | |
1016 | } |