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
4 //! ought to be merged. This code is intended for use in NLL and chalk.
6 //! Here are the key differences:
8 //! - This code may choose to bypass some checks (e.g., the occurs check)
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.
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
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
24 use crate::infer::combine::ConstEquateRelation;
25 use crate::infer::InferCtxt;
26 use crate::infer::{ConstVarValue, ConstVariableValue};
27 use crate::infer::{TypeVariableOrigin, TypeVariableOriginKind};
28 use crate::traits::{Obligation, PredicateObligation};
29 use rustc_data_structures::fx::FxHashMap;
30 use rustc_middle::traits::ObligationCause;
31 use rustc_middle::ty::error::TypeError;
32 use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
33 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
34 use rustc_middle::ty::{self, InferConst, Ty, TyCtxt};
37 use std::ops::ControlFlow;
40 pub enum NormalizationStrategy {
45 pub struct TypeRelating<'me, 'tcx, D>
47 D: TypeRelatingDelegate<'tcx>,
49 infcx: &'me InferCtxt<'tcx>,
51 /// Callback to use when we deduce an outlives relationship.
54 /// How are we relating `a` and `b`?
56 /// - Covariant means `a <: b`.
57 /// - Contravariant means `b <: a`.
58 /// - Invariant means `a == b.
59 /// - Bivariant means that it doesn't matter.
60 ambient_variance: ty::Variance,
62 ambient_variance_info: ty::VarianceDiagInfo<'tcx>,
64 /// When we pass through a set of binders (e.g., when looking into
65 /// a `fn` type), we push a new bound region scope onto here. This
66 /// will contain the instantiated region for each region in those
67 /// binders. When we then encounter a `ReLateBound(d, br)`, we can
68 /// use the De Bruijn index `d` to find the right scope, and then
69 /// bound region name `br` to find the specific instantiation from
70 /// within that scope. See `replace_bound_region`.
72 /// This field stores the instantiations for late-bound regions in
74 a_scopes: Vec<BoundRegionScope<'tcx>>,
76 /// Same as `a_scopes`, but for the `b` type.
77 b_scopes: Vec<BoundRegionScope<'tcx>>,
80 pub trait TypeRelatingDelegate<'tcx> {
81 fn param_env(&self) -> ty::ParamEnv<'tcx>;
82 fn span(&self) -> Span;
84 /// Push a constraint `sup: sub` -- this constraint must be
85 /// satisfied for the two types to be related. `sub` and `sup` may
86 /// be regions from the type or new variables created through the
90 sup: ty::Region<'tcx>,
91 sub: ty::Region<'tcx>,
92 info: ty::VarianceDiagInfo<'tcx>,
95 fn register_obligations(&mut self, obligations: Vec<PredicateObligation<'tcx>>);
97 /// Creates a new universe index. Used when instantiating placeholders.
98 fn create_next_universe(&mut self) -> ty::UniverseIndex;
100 /// Creates a new region variable representing a higher-ranked
101 /// region that is instantiated existentially. This creates an
102 /// inference variable, typically.
104 /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
105 /// we will invoke this method to instantiate `'a` with an
106 /// inference variable (though `'b` would be instantiated first,
107 /// as a placeholder).
108 fn next_existential_region_var(&mut self, was_placeholder: bool) -> ty::Region<'tcx>;
110 /// Creates a new region variable representing a
111 /// higher-ranked region that is instantiated universally.
112 /// This creates a new region placeholder, typically.
114 /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
115 /// we will invoke this method to instantiate `'b` with a
116 /// placeholder region.
117 fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>;
119 /// Creates a new existential region in the given universe. This
120 /// is used when handling subtyping and type variables -- if we
121 /// have that `?X <: Foo<'a>`, for example, we would instantiate
122 /// `?X` with a type like `Foo<'?0>` where `'?0` is a fresh
123 /// existential variable created by this function. We would then
124 /// relate `Foo<'?0>` with `Foo<'a>` (and probably add an outlives
125 /// relation stating that `'?0: 'a`).
126 fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
128 /// Define the normalization strategy to use, eager or lazy.
129 fn normalization() -> NormalizationStrategy;
131 /// Enables some optimizations if we do not expect inference variables
132 /// in the RHS of the relation.
133 fn forbid_inference_vars() -> bool;
136 #[derive(Clone, Debug, Default)]
137 struct BoundRegionScope<'tcx> {
138 map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
141 #[derive(Copy, Clone)]
142 struct UniversallyQuantified(bool);
144 impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D>
146 D: TypeRelatingDelegate<'tcx>,
148 pub fn new(infcx: &'me InferCtxt<'tcx>, delegate: D, ambient_variance: ty::Variance) -> Self {
153 ambient_variance_info: ty::VarianceDiagInfo::default(),
159 fn ambient_covariance(&self) -> bool {
160 match self.ambient_variance {
161 ty::Variance::Covariant | ty::Variance::Invariant => true,
162 ty::Variance::Contravariant | ty::Variance::Bivariant => false,
166 fn ambient_contravariance(&self) -> bool {
167 match self.ambient_variance {
168 ty::Variance::Contravariant | ty::Variance::Invariant => true,
169 ty::Variance::Covariant | ty::Variance::Bivariant => false,
175 value: ty::Binder<'tcx, impl Relate<'tcx>>,
176 universally_quantified: UniversallyQuantified,
177 ) -> BoundRegionScope<'tcx> {
178 let mut scope = BoundRegionScope::default();
180 // Create a callback that creates (via the delegate) either an
181 // existential or placeholder region as needed.
182 let mut next_region = {
183 let delegate = &mut self.delegate;
184 let mut lazy_universe = None;
185 move |br: ty::BoundRegion| {
186 if universally_quantified.0 {
187 // The first time this closure is called, create a
188 // new universe for the placeholders we will make
190 let universe = lazy_universe.unwrap_or_else(|| {
191 let universe = delegate.create_next_universe();
192 lazy_universe = Some(universe);
196 let placeholder = ty::PlaceholderRegion { universe, name: br.kind };
197 delegate.next_placeholder_region(placeholder)
199 delegate.next_existential_region_var(true)
204 value.skip_binder().visit_with(&mut ScopeInstantiator {
205 next_region: &mut next_region,
206 target_index: ty::INNERMOST,
207 bound_region_scope: &mut scope,
213 /// When we encounter binders during the type traversal, we record
214 /// the value to substitute for each of the things contained in
215 /// that binder. (This will be either a universal placeholder or
216 /// an existential inference variable.) Given the De Bruijn index
217 /// `debruijn` (and name `br`) of some binder we have now
218 /// encountered, this routine finds the value that we instantiated
219 /// the region with; to do so, it indexes backwards into the list
220 /// of ambient scopes `scopes`.
221 fn lookup_bound_region(
222 debruijn: ty::DebruijnIndex,
223 br: &ty::BoundRegion,
224 first_free_index: ty::DebruijnIndex,
225 scopes: &[BoundRegionScope<'tcx>],
226 ) -> ty::Region<'tcx> {
227 // The debruijn index is a "reverse index" into the
228 // scopes listing. So when we have INNERMOST (0), we
229 // want the *last* scope pushed, and so forth.
230 let debruijn_index = debruijn.index() - first_free_index.index();
231 let scope = &scopes[scopes.len() - debruijn_index - 1];
233 // Find this bound region in that scope to map to a
234 // particular region.
238 /// If `r` is a bound region, find the scope in which it is bound
239 /// (from `scopes`) and return the value that we instantiated it
240 /// with. Otherwise just return `r`.
241 fn replace_bound_region(
244 first_free_index: ty::DebruijnIndex,
245 scopes: &[BoundRegionScope<'tcx>],
246 ) -> ty::Region<'tcx> {
247 debug!("replace_bound_regions(scopes={:?})", scopes);
248 if let ty::ReLateBound(debruijn, br) = *r {
249 Self::lookup_bound_region(debruijn, &br, first_free_index, scopes)
255 /// Push a new outlives requirement into our output set of
259 sup: ty::Region<'tcx>,
260 sub: ty::Region<'tcx>,
261 info: ty::VarianceDiagInfo<'tcx>,
263 debug!("push_outlives({:?}: {:?})", sup, sub);
265 self.delegate.push_outlives(sup, sub, info);
268 /// Relate a projection type and some value type lazily. This will always
269 /// succeed, but we push an additional `ProjectionEq` goal depending
270 /// on the value type:
271 /// - if the value type is any type `T` which is not a projection, we push
272 /// `ProjectionEq(projection = T)`.
273 /// - if the value type is another projection `other_projection`, we create
274 /// a new inference variable `?U` and push the two goals
275 /// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
276 fn relate_projection_ty(
278 projection_ty: ty::ProjectionTy<'tcx>,
281 use rustc_span::DUMMY_SP;
283 match *value_ty.kind() {
284 ty::Projection(other_projection_ty) => {
285 let var = self.infcx.next_ty_var(TypeVariableOrigin {
286 kind: TypeVariableOriginKind::MiscVariable,
289 // FIXME(lazy-normalization): This will always ICE, because the recursive
290 // call will end up in the _ arm below.
291 self.relate_projection_ty(projection_ty, var);
292 self.relate_projection_ty(other_projection_ty, var);
296 _ => bug!("should never be invoked with eager normalization"),
300 /// Relate a type inference variable with a value type. This works
301 /// by creating a "generalization" G of the value where all the
302 /// lifetimes are replaced with fresh inference values. This
303 /// generalization G becomes the value of the inference variable,
304 /// and is then related in turn to the value. So e.g. if you had
305 /// `vid = ?0` and `value = &'a u32`, we might first instantiate
306 /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
307 /// and then relate `&'0 u32` with `&'a u32` (resulting in
308 /// relations between `'0` and `'a`).
310 /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
311 /// -- in other words, it is always an (unresolved) inference
312 /// variable `vid` and a type `ty` that are being related, but the
313 /// vid may appear either as the "a" type or the "b" type,
314 /// depending on where it appears in the tuple. The trait
315 /// `VidValuePair` lets us work with the vid/type while preserving
316 /// the "sidedness" when necessary -- the sidedness is relevant in
317 /// particular for the variance and set of in-scope things.
318 fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
321 ) -> RelateResult<'tcx, Ty<'tcx>> {
322 debug!("relate_ty_var({:?})", pair);
324 let vid = pair.vid();
325 let value_ty = pair.value_ty();
327 // FIXME(invariance) -- this logic assumes invariance, but that is wrong.
328 // This only presently applies to chalk integration, as NLL
329 // doesn't permit type variables to appear on both sides (and
330 // doesn't use lazy norm).
331 match *value_ty.kind() {
332 ty::Infer(ty::TyVar(value_vid)) => {
333 // Two type variables: just equate them.
334 self.infcx.inner.borrow_mut().type_variables().equate(vid, value_vid);
338 ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
339 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
345 let generalized_ty = self.generalize_value(value_ty, vid)?;
346 debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
348 if D::forbid_inference_vars() {
349 // In NLL, we don't have type inference variables
350 // floating around, so we can do this rather imprecise
351 // variant of the occurs-check.
352 assert!(!generalized_ty.has_non_region_infer());
355 self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
357 // The generalized values we extract from `canonical_var_values` have
358 // been fully instantiated and hence the set of scopes we have
359 // doesn't matter -- just to be sure, put an empty vector
361 let old_a_scopes = std::mem::take(pair.vid_scopes(self));
363 // Relate the generalized kind to the original one.
364 let result = pair.relate_generalized_ty(self, generalized_ty);
366 // Restore the old scopes now.
367 *pair.vid_scopes(self) = old_a_scopes;
369 debug!("relate_ty_var: complete, result = {:?}", result);
373 fn generalize_value<T: Relate<'tcx>>(
377 ) -> RelateResult<'tcx, T> {
378 let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
380 let mut generalizer = TypeGeneralizer {
382 delegate: &mut self.delegate,
383 first_free_index: ty::INNERMOST,
384 ambient_variance: self.ambient_variance,
385 for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
389 generalizer.relate(value, value)
392 fn relate_opaques(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
393 let (a, b) = if self.a_is_expected() { (a, b) } else { (b, a) };
394 let mut generalize = |ty, ty_is_expected| {
395 let var = self.infcx.next_ty_var_id_in_universe(
397 kind: TypeVariableOriginKind::MiscVariable,
398 span: self.delegate.span(),
400 ty::UniverseIndex::ROOT,
403 self.relate_ty_var((ty, var))
405 self.relate_ty_var((var, ty))
408 let (a, b) = match (a.kind(), b.kind()) {
409 (&ty::Opaque(..), _) => (a, generalize(b, false)?),
410 (_, &ty::Opaque(..)) => (generalize(a, true)?, b),
413 let cause = ObligationCause::dummy_with_span(self.delegate.span());
414 let obligations = self
416 .handle_opaque_type(a, b, true, &cause, self.delegate.param_env())?
418 self.delegate.register_obligations(obligations);
419 trace!(a = ?a.kind(), b = ?b.kind(), "opaque type instantiated");
424 /// When we instantiate an inference variable with a value in
425 /// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
426 /// but the ordering may vary (depending on whether the inference
427 /// variable was found on the `a` or `b` sides). Therefore, this trait
428 /// allows us to factor out common code, while preserving the order
430 trait VidValuePair<'tcx>: Debug {
431 /// Extract the inference variable (which could be either the
432 /// first or second part of the tuple).
433 fn vid(&self) -> ty::TyVid;
435 /// Extract the value it is being related to (which will be the
436 /// opposite part of the tuple from the vid).
437 fn value_ty(&self) -> Ty<'tcx>;
439 /// Extract the scopes that apply to whichever side of the tuple
440 /// the vid was found on. See the comment where this is called
441 /// for more details on why we want them.
442 fn vid_scopes<'r, D: TypeRelatingDelegate<'tcx>>(
444 relate: &'r mut TypeRelating<'_, 'tcx, D>,
445 ) -> &'r mut Vec<BoundRegionScope<'tcx>>;
447 /// Given a generalized type G that should replace the vid, relate
448 /// G to the value, putting G on whichever side the vid would have
450 fn relate_generalized_ty<D>(
452 relate: &mut TypeRelating<'_, 'tcx, D>,
453 generalized_ty: Ty<'tcx>,
454 ) -> RelateResult<'tcx, Ty<'tcx>>
456 D: TypeRelatingDelegate<'tcx>;
459 impl<'tcx> VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
460 fn vid(&self) -> ty::TyVid {
464 fn value_ty(&self) -> Ty<'tcx> {
468 fn vid_scopes<'r, D>(
470 relate: &'r mut TypeRelating<'_, 'tcx, D>,
471 ) -> &'r mut Vec<BoundRegionScope<'tcx>>
473 D: TypeRelatingDelegate<'tcx>,
478 fn relate_generalized_ty<D>(
480 relate: &mut TypeRelating<'_, 'tcx, D>,
481 generalized_ty: Ty<'tcx>,
482 ) -> RelateResult<'tcx, Ty<'tcx>>
484 D: TypeRelatingDelegate<'tcx>,
486 relate.relate(generalized_ty, self.value_ty())
490 // In this case, the "vid" is the "b" type.
491 impl<'tcx> VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
492 fn vid(&self) -> ty::TyVid {
496 fn value_ty(&self) -> Ty<'tcx> {
500 fn vid_scopes<'r, D>(
502 relate: &'r mut TypeRelating<'_, 'tcx, D>,
503 ) -> &'r mut Vec<BoundRegionScope<'tcx>>
505 D: TypeRelatingDelegate<'tcx>,
510 fn relate_generalized_ty<D>(
512 relate: &mut TypeRelating<'_, 'tcx, D>,
513 generalized_ty: Ty<'tcx>,
514 ) -> RelateResult<'tcx, Ty<'tcx>>
516 D: TypeRelatingDelegate<'tcx>,
518 relate.relate(self.value_ty(), generalized_ty)
522 impl<'tcx, D> TypeRelation<'tcx> for TypeRelating<'_, 'tcx, D>
524 D: TypeRelatingDelegate<'tcx>,
526 fn tcx(&self) -> TyCtxt<'tcx> {
530 fn intercrate(&self) -> bool {
531 self.infcx.intercrate
534 fn param_env(&self) -> ty::ParamEnv<'tcx> {
535 self.delegate.param_env()
538 fn tag(&self) -> &'static str {
542 fn a_is_expected(&self) -> bool {
546 fn mark_ambiguous(&mut self) {
547 let cause = ObligationCause::dummy_with_span(self.delegate.span());
548 let param_env = self.delegate.param_env();
549 self.delegate.register_obligations(vec![Obligation::new(
553 ty::Binder::dummy(ty::PredicateKind::Ambiguous),
557 #[instrument(skip(self, info), level = "trace", ret)]
558 fn relate_with_variance<T: Relate<'tcx>>(
560 variance: ty::Variance,
561 info: ty::VarianceDiagInfo<'tcx>,
564 ) -> RelateResult<'tcx, T> {
565 let old_ambient_variance = self.ambient_variance;
566 self.ambient_variance = self.ambient_variance.xform(variance);
567 self.ambient_variance_info = self.ambient_variance_info.xform(info);
569 debug!(?self.ambient_variance);
570 // In a bivariant context this always succeeds.
572 if self.ambient_variance == ty::Variance::Bivariant { a } else { self.relate(a, b)? };
574 self.ambient_variance = old_ambient_variance;
579 #[instrument(skip(self), level = "debug")]
580 fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
581 let infcx = self.infcx;
583 let a = self.infcx.shallow_resolve(a);
585 if !D::forbid_inference_vars() {
586 b = self.infcx.shallow_resolve(b);
590 // Subtle: if a or b has a bound variable that we are lazily
591 // substituting, then even if a == b, it could be that the values we
592 // will substitute for those bound variables are *not* the same, and
593 // hence returning `Ok(a)` is incorrect.
594 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
599 match (a.kind(), b.kind()) {
600 (_, &ty::Infer(ty::TyVar(vid))) => {
601 if D::forbid_inference_vars() {
602 // Forbid inference variables in the RHS.
603 bug!("unexpected inference var {:?}", b)
605 self.relate_ty_var((a, vid))
609 (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
611 (&ty::Opaque(a_def_id, _), &ty::Opaque(b_def_id, _)) if a_def_id == b_def_id => {
612 infcx.super_combine_tys(self, a, b).or_else(|err| {
613 self.tcx().sess.delay_span_bug(
614 self.delegate.span(),
615 "failure to relate an opaque to itself should result in an error later on",
617 if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) }
620 (&ty::Opaque(did, ..), _) | (_, &ty::Opaque(did, ..)) if did.is_local() => {
621 self.relate_opaques(a, b)
624 (&ty::Projection(projection_ty), _)
625 if D::normalization() == NormalizationStrategy::Lazy =>
627 Ok(self.relate_projection_ty(projection_ty, b))
630 (_, &ty::Projection(projection_ty))
631 if D::normalization() == NormalizationStrategy::Lazy =>
633 Ok(self.relate_projection_ty(projection_ty, a))
637 debug!(?a, ?b, ?self.ambient_variance);
639 // Will also handle unification of `IntVar` and `FloatVar`.
640 self.infcx.super_combine_tys(self, a, b)
645 #[instrument(skip(self), level = "trace")]
650 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
651 debug!(?self.ambient_variance);
653 let v_a = self.replace_bound_region(a, ty::INNERMOST, &self.a_scopes);
654 let v_b = self.replace_bound_region(b, ty::INNERMOST, &self.b_scopes);
659 if self.ambient_covariance() {
660 // Covariance: a <= b. Hence, `b: a`.
661 self.push_outlives(v_b, v_a, self.ambient_variance_info);
664 if self.ambient_contravariance() {
665 // Contravariant: b <= a. Hence, `a: b`.
666 self.push_outlives(v_a, v_b, self.ambient_variance_info);
675 mut b: ty::Const<'tcx>,
676 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
677 let a = self.infcx.shallow_resolve(a);
679 if !D::forbid_inference_vars() {
680 b = self.infcx.shallow_resolve(b);
684 ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
685 // Forbid inference variables in the RHS.
686 self.infcx.tcx.sess.delay_span_bug(
687 self.delegate.span(),
688 format!("unexpected inference var {:?}", b,),
692 // FIXME(invariance): see the related FIXME above.
693 _ => self.infcx.super_combine_consts(self, a, b),
697 #[instrument(skip(self), level = "trace")]
700 a: ty::Binder<'tcx, T>,
701 b: ty::Binder<'tcx, T>,
702 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
709 // for<'a> fn(&'a u32) -> &'a u32 <:
710 // fn(&'b u32) -> &'b u32
716 // fn(&'a u32) -> &'a u32 <:
717 // for<'b> fn(&'b u32) -> &'b u32
720 // We therefore proceed as follows:
722 // - Instantiate binders on `b` universally, yielding a universe U1.
723 // - Instantiate binders on `a` existentially in U1.
725 debug!(?self.ambient_variance);
727 if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) {
728 // Fast path for the common case.
730 return Ok(ty::Binder::dummy(a));
733 if self.ambient_covariance() {
734 // Covariance, so we want `for<..> A <: for<..> B` --
735 // therefore we compare any instantiation of A (i.e., A
736 // instantiated with existentials) against every
737 // instantiation of B (i.e., B instantiated with
740 let b_scope = self.create_scope(b, UniversallyQuantified(true));
741 let a_scope = self.create_scope(a, UniversallyQuantified(false));
743 debug!(?a_scope, "(existential)");
744 debug!(?b_scope, "(universal)");
746 self.b_scopes.push(b_scope);
747 self.a_scopes.push(a_scope);
749 // Reset the ambient variance to covariant. This is needed
750 // to correctly handle cases like
752 // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32)
754 // Somewhat surprisingly, these two types are actually
755 // **equal**, even though the one on the right looks more
756 // polymorphic. The reason is due to subtyping. To see it,
757 // consider that each function can call the other:
759 // - The left function can call the right with `'b` and
760 // `'c` both equal to `'a`
762 // - The right function can call the left with `'a` set to
763 // `{P}`, where P is the point in the CFG where the call
764 // itself occurs. Note that `'b` and `'c` must both
765 // include P. At the point, the call works because of
766 // subtyping (i.e., `&'b u32 <: &{P} u32`).
767 let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant);
769 self.relate(a.skip_binder(), b.skip_binder())?;
771 self.ambient_variance = variance;
773 self.b_scopes.pop().unwrap();
774 self.a_scopes.pop().unwrap();
777 if self.ambient_contravariance() {
778 // Contravariance, so we want `for<..> A :> for<..> B`
779 // -- therefore we compare every instantiation of A (i.e.,
780 // A instantiated with universals) against any
781 // instantiation of B (i.e., B instantiated with
782 // existentials). Opposite of above.
784 let a_scope = self.create_scope(a, UniversallyQuantified(true));
785 let b_scope = self.create_scope(b, UniversallyQuantified(false));
787 debug!(?a_scope, "(universal)");
788 debug!(?b_scope, "(existential)");
790 self.a_scopes.push(a_scope);
791 self.b_scopes.push(b_scope);
793 // Reset ambient variance to contravariance. See the
794 // covariant case above for an explanation.
796 std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
798 self.relate(a.skip_binder(), b.skip_binder())?;
800 self.ambient_variance = variance;
802 self.b_scopes.pop().unwrap();
803 self.a_scopes.pop().unwrap();
810 impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
812 D: TypeRelatingDelegate<'tcx>,
814 fn const_equate_obligation(&mut self, _a: ty::Const<'tcx>, _b: ty::Const<'tcx>) {
815 // We don't have to worry about the equality of consts during borrow checking
816 // as consts always have a static lifetime.
817 // FIXME(oli-obk): is this really true? We can at least have HKL and with
818 // inline consts we may have further lifetimes that may be unsound to treat as
823 /// When we encounter a binder like `for<..> fn(..)`, we actually have
824 /// to walk the `fn` value to find all the values bound by the `for`
825 /// (these are not explicitly present in the ty representation right
826 /// now). This visitor handles that: it descends the type, tracking
827 /// binder depth, and finds late-bound regions targeting the
828 /// `for<..`>. For each of those, it creates an entry in
829 /// `bound_region_scope`.
830 struct ScopeInstantiator<'me, 'tcx> {
831 next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
832 // The debruijn index of the scope we are instantiating.
833 target_index: ty::DebruijnIndex,
834 bound_region_scope: &'me mut BoundRegionScope<'tcx>,
837 impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
838 fn visit_binder<T: TypeVisitable<'tcx>>(
840 t: &ty::Binder<'tcx, T>,
841 ) -> ControlFlow<Self::BreakTy> {
842 self.target_index.shift_in(1);
843 t.super_visit_with(self);
844 self.target_index.shift_out(1);
846 ControlFlow::CONTINUE
849 fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
850 let ScopeInstantiator { bound_region_scope, next_region, .. } = self;
853 ty::ReLateBound(debruijn, br) if debruijn == self.target_index => {
854 bound_region_scope.map.entry(br).or_insert_with(|| next_region(br));
860 ControlFlow::CONTINUE
864 /// The "type generalizer" is used when handling inference variables.
866 /// The basic strategy for handling a constraint like `?A <: B` is to
867 /// apply a "generalization strategy" to the type `B` -- this replaces
868 /// all the lifetimes in the type `B` with fresh inference
869 /// variables. (You can read more about the strategy in this [blog
872 /// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
873 /// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
874 /// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
875 /// establishes `'0: 'x` as a constraint.
877 /// As a side-effect of this generalization procedure, we also replace
878 /// all the bound regions that we have traversed with concrete values,
879 /// so that the resulting generalized type is independent from the
882 /// [blog post]: https://is.gd/0hKvIr
883 struct TypeGeneralizer<'me, 'tcx, D>
885 D: TypeRelatingDelegate<'tcx>,
887 infcx: &'me InferCtxt<'tcx>,
889 delegate: &'me mut D,
891 /// After we generalize this type, we are going to relate it to
892 /// some other type. What will be the variance at this point?
893 ambient_variance: ty::Variance,
895 first_free_index: ty::DebruijnIndex,
897 /// The vid of the type variable that is in the process of being
898 /// instantiated. If we find this within the value we are folding,
899 /// that means we would have created a cyclic value.
900 for_vid_sub_root: ty::TyVid,
902 /// The universe of the type variable that is in the process of being
903 /// instantiated. If we find anything that this universe cannot name,
904 /// we reject the relation.
905 universe: ty::UniverseIndex,
908 impl<'tcx, D> TypeRelation<'tcx> for TypeGeneralizer<'_, 'tcx, D>
910 D: TypeRelatingDelegate<'tcx>,
912 fn tcx(&self) -> TyCtxt<'tcx> {
916 fn intercrate(&self) -> bool {
917 assert!(!self.infcx.intercrate);
921 fn param_env(&self) -> ty::ParamEnv<'tcx> {
922 self.delegate.param_env()
925 fn tag(&self) -> &'static str {
929 fn a_is_expected(&self) -> bool {
933 fn mark_ambiguous(&mut self) {
937 fn relate_with_variance<T: Relate<'tcx>>(
939 variance: ty::Variance,
940 _info: ty::VarianceDiagInfo<'tcx>,
943 ) -> RelateResult<'tcx, T> {
945 "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
949 let old_ambient_variance = self.ambient_variance;
950 self.ambient_variance = self.ambient_variance.xform(variance);
953 "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
954 self.ambient_variance
957 let r = self.relate(a, b)?;
959 self.ambient_variance = old_ambient_variance;
961 debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
966 fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
967 use crate::infer::type_variable::TypeVariableValue;
969 debug!("TypeGeneralizer::tys(a={:?})", a);
972 ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
973 if D::forbid_inference_vars() =>
975 bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
978 ty::Infer(ty::TyVar(vid)) => {
979 let mut inner = self.infcx.inner.borrow_mut();
980 let variables = &mut inner.type_variables();
981 let vid = variables.root_var(vid);
982 let sub_vid = variables.sub_root_var(vid);
983 if sub_vid == self.for_vid_sub_root {
984 // If sub-roots are equal, then `for_vid` and
985 // `vid` are related via subtyping.
986 debug!("TypeGeneralizer::tys: occurs check failed");
987 Err(TypeError::Mismatch)
989 match variables.probe(vid) {
990 TypeVariableValue::Known { value: u } => {
994 TypeVariableValue::Unknown { universe: _universe } => {
995 if self.ambient_variance == ty::Bivariant {
996 // FIXME: we may need a WF predicate (related to #54105).
999 let origin = *variables.var_origin(vid);
1001 // Replacing with a new variable in the universe `self.universe`,
1002 // it will be unified later with the original type variable in
1003 // the universe `_universe`.
1004 let new_var_id = variables.new_var(self.universe, origin);
1006 let u = self.tcx().mk_ty_var(new_var_id);
1007 debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
1014 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
1015 // No matter what mode we are in,
1016 // integer/floating-point types must be equal to be
1021 ty::Placeholder(placeholder) => {
1022 if self.universe.cannot_name(placeholder.universe) {
1024 "TypeGeneralizer::tys: root universe {:?} cannot name\
1025 placeholder in universe {:?}",
1026 self.universe, placeholder.universe
1028 Err(TypeError::Mismatch)
1034 _ => relate::super_relate_tys(self, a, a),
1040 a: ty::Region<'tcx>,
1041 _: ty::Region<'tcx>,
1042 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
1043 debug!("TypeGeneralizer::regions(a={:?})", a);
1045 if let ty::ReLateBound(debruijn, _) = *a && debruijn < self.first_free_index {
1049 // For now, we just always create a fresh region variable to
1050 // replace all the regions in the source type. In the main
1051 // type checker, we special case the case where the ambient
1052 // variance is `Invariant` and try to avoid creating a fresh
1053 // region variable, but since this comes up so much less in
1054 // NLL (only when users use `_` etc) it is much less
1057 // As an aside, since these new variables are created in
1058 // `self.universe` universe, this also serves to enforce the
1059 // universe scoping rules.
1061 // FIXME(#54105) -- if the ambient variance is bivariant,
1062 // though, we may however need to check well-formedness or
1063 // risk a problem like #41677 again.
1065 let replacement_region_vid = self.delegate.generalize_existential(self.universe);
1067 Ok(replacement_region_vid)
1074 ) -> RelateResult<'tcx, ty::Const<'tcx>> {
1076 ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
1077 bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
1079 ty::ConstKind::Infer(InferConst::Var(vid)) => {
1080 let mut inner = self.infcx.inner.borrow_mut();
1081 let variable_table = &mut inner.const_unification_table();
1082 let var_value = variable_table.probe_value(vid);
1083 match var_value.val.known() {
1084 Some(u) => self.relate(u, u),
1086 let new_var_id = variable_table.new_key(ConstVarValue {
1087 origin: var_value.origin,
1088 val: ConstVariableValue::Unknown { universe: self.universe },
1090 Ok(self.tcx().mk_const(new_var_id, a.ty()))
1094 ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
1095 _ => relate::super_relate_consts(self, a, a),
1101 a: ty::Binder<'tcx, T>,
1102 _: ty::Binder<'tcx, T>,
1103 ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
1107 debug!("TypeGeneralizer::binders(a={:?})", a);
1109 self.first_free_index.shift_in(1);
1110 let result = self.relate(a.skip_binder(), a.skip_binder())?;
1111 self.first_free_index.shift_out(1);
1112 Ok(a.rebind(result))