]> git.proxmox.com Git - rustc.git/blame - src/librustc_infer/infer/nll_relate/mod.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_infer / infer / nll_relate / mod.rs
CommitLineData
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 24use crate::infer::combine::ConstEquateRelation;
0bf4aa26 25use crate::infer::InferCtxt;
dfeec247 26use crate::infer::{ConstVarValue, ConstVariableValue};
0bf4aa26 27use rustc_data_structures::fx::FxHashMap;
ba9703b0
XL
28use rustc_middle::ty::error::TypeError;
29use rustc_middle::ty::fold::{TypeFoldable, TypeVisitor};
30use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
31use rustc_middle::ty::subst::GenericArg;
32use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
532ac7d7 33use std::fmt::Debug;
0bf4aa26 34
e74abb32 35#[derive(PartialEq)]
a1dfa0c6
XL
36pub enum NormalizationStrategy {
37 Lazy,
38 Eager,
39}
40
dc9dc135 41pub struct TypeRelating<'me, 'tcx, D>
0bf4aa26
XL
42where
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
74pub 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)]
123struct ScopesAndKind<'tcx> {
124 scopes: Vec<BoundRegionScope<'tcx>>,
e74abb32 125 kind: GenericArg<'tcx>,
0bf4aa26
XL
126}
127
128#[derive(Clone, Debug, Default)]
129struct BoundRegionScope<'tcx> {
130 map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
131}
132
133#[derive(Copy, Clone)]
134struct UniversallyQuantified(bool);
135
dc9dc135 136impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D>
0bf4aa26
XL
137where
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.
382trait 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
411impl 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.
443impl 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 474impl<D> TypeRelation<'tcx> for TypeRelating<'me, 'tcx, D>
0bf4aa26
XL
475where
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
726impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
727where
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 742struct 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
749impl<'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 792struct TypeGeneralizer<'me, 'tcx, D>
0bf4aa26 793where
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 817impl<D> TypeRelation<'tcx> for TypeGeneralizer<'me, 'tcx, D>
0bf4aa26
XL
818where
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}