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 rustc_data_structures::fx::FxHashMap;
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::{self, InferConst, Ty, TyCtxt};
35 pub enum NormalizationStrategy {
40 pub struct TypeRelating<'me, 'tcx, D>
42 D: TypeRelatingDelegate<'tcx>,
44 infcx: &'me InferCtxt<'me, 'tcx>,
46 /// Callback to use when we deduce an outlives relationship
49 /// How are we relating `a` and `b`?
51 /// - Covariant means `a <: b`.
52 /// - Contravariant means `b <: a`.
53 /// - Invariant means `a == b.
54 /// - Bivariant means that it doesn't matter.
55 ambient_variance: ty::Variance,
57 /// When we pass through a set of binders (e.g., when looking into
58 /// a `fn` type), we push a new bound region scope onto here. This
59 /// will contain the instantiated region for each region in those
60 /// binders. When we then encounter a `ReLateBound(d, br)`, we can
61 /// use the De Bruijn index `d` to find the right scope, and then
62 /// bound region name `br` to find the specific instantiation from
63 /// within that scope. See `replace_bound_region`.
65 /// This field stores the instantiations for late-bound regions in
67 a_scopes: Vec<BoundRegionScope<'tcx>>,
69 /// Same as `a_scopes`, but for the `b` type.
70 b_scopes: Vec<BoundRegionScope<'tcx>>,
73 pub trait TypeRelatingDelegate<'tcx> {
74 /// Push a constraint `sup: sub` -- this constraint must be
75 /// satisfied for the two types to be related. `sub` and `sup` may
76 /// be regions from the type or new variables created through the
78 fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>);
80 fn const_equate(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>);
82 /// Creates a new universe index. Used when instantiating placeholders.
83 fn create_next_universe(&mut self) -> ty::UniverseIndex;
85 /// Creates a new region variable representing a higher-ranked
86 /// region that is instantiated existentially. This creates an
87 /// inference variable, typically.
89 /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
90 /// we will invoke this method to instantiate `'a` with an
91 /// inference variable (though `'b` would be instantiated first,
92 /// as a placeholder).
93 fn next_existential_region_var(&mut self, was_placeholder: bool) -> ty::Region<'tcx>;
95 /// Creates a new region variable representing a
96 /// higher-ranked region that is instantiated universally.
97 /// This creates a new region placeholder, typically.
99 /// So e.g., if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
100 /// we will invoke this method to instantiate `'b` with a
101 /// placeholder region.
102 fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx>;
104 /// Creates a new existential region in the given universe. This
105 /// is used when handling subtyping and type variables -- if we
106 /// have that `?X <: Foo<'a>`, for example, we would instantiate
107 /// `?X` with a type like `Foo<'?0>` where `'?0` is a fresh
108 /// existential variable created by this function. We would then
109 /// relate `Foo<'?0>` with `Foo<'a>` (and probably add an outlives
110 /// relation stating that `'?0: 'a`).
111 fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx>;
113 /// Define the normalization strategy to use, eager or lazy.
114 fn normalization() -> NormalizationStrategy;
116 /// Enables some optimizations if we do not expect inference variables
117 /// in the RHS of the relation.
118 fn forbid_inference_vars() -> bool;
121 #[derive(Clone, Debug, Default)]
122 struct BoundRegionScope<'tcx> {
123 map: FxHashMap<ty::BoundRegion, ty::Region<'tcx>>,
126 #[derive(Copy, Clone)]
127 struct UniversallyQuantified(bool);
129 impl<'me, 'tcx, D> TypeRelating<'me, 'tcx, D>
131 D: TypeRelatingDelegate<'tcx>,
134 infcx: &'me InferCtxt<'me, 'tcx>,
136 ambient_variance: ty::Variance,
138 Self { infcx, delegate, ambient_variance, a_scopes: vec![], b_scopes: vec![] }
141 fn ambient_covariance(&self) -> bool {
142 match self.ambient_variance {
143 ty::Variance::Covariant | ty::Variance::Invariant => true,
144 ty::Variance::Contravariant | ty::Variance::Bivariant => false,
148 fn ambient_contravariance(&self) -> bool {
149 match self.ambient_variance {
150 ty::Variance::Contravariant | ty::Variance::Invariant => true,
151 ty::Variance::Covariant | ty::Variance::Bivariant => false,
157 value: ty::Binder<impl Relate<'tcx>>,
158 universally_quantified: UniversallyQuantified,
159 ) -> BoundRegionScope<'tcx> {
160 let mut scope = BoundRegionScope::default();
162 // Create a callback that creates (via the delegate) either an
163 // existential or placeholder region as needed.
164 let mut next_region = {
165 let delegate = &mut self.delegate;
166 let mut lazy_universe = None;
167 move |br: ty::BoundRegion| {
168 if universally_quantified.0 {
169 // The first time this closure is called, create a
170 // new universe for the placeholders we will make
172 let universe = lazy_universe.unwrap_or_else(|| {
173 let universe = delegate.create_next_universe();
174 lazy_universe = Some(universe);
178 let placeholder = ty::PlaceholderRegion { universe, name: br };
179 delegate.next_placeholder_region(placeholder)
181 delegate.next_existential_region_var(true)
186 value.skip_binder().visit_with(&mut ScopeInstantiator {
187 next_region: &mut next_region,
188 target_index: ty::INNERMOST,
189 bound_region_scope: &mut scope,
195 /// When we encounter binders during the type traversal, we record
196 /// the value to substitute for each of the things contained in
197 /// that binder. (This will be either a universal placeholder or
198 /// an existential inference variable.) Given the De Bruijn index
199 /// `debruijn` (and name `br`) of some binder we have now
200 /// encountered, this routine finds the value that we instantiated
201 /// the region with; to do so, it indexes backwards into the list
202 /// of ambient scopes `scopes`.
203 fn lookup_bound_region(
204 debruijn: ty::DebruijnIndex,
205 br: &ty::BoundRegion,
206 first_free_index: ty::DebruijnIndex,
207 scopes: &[BoundRegionScope<'tcx>],
208 ) -> ty::Region<'tcx> {
209 // The debruijn index is a "reverse index" into the
210 // scopes listing. So when we have INNERMOST (0), we
211 // want the *last* scope pushed, and so forth.
212 let debruijn_index = debruijn.index() - first_free_index.index();
213 let scope = &scopes[scopes.len() - debruijn_index - 1];
215 // Find this bound region in that scope to map to a
216 // particular region.
220 /// If `r` is a bound region, find the scope in which it is bound
221 /// (from `scopes`) and return the value that we instantiated it
222 /// with. Otherwise just return `r`.
223 fn replace_bound_region(
226 first_free_index: ty::DebruijnIndex,
227 scopes: &[BoundRegionScope<'tcx>],
228 ) -> ty::Region<'tcx> {
229 debug!("replace_bound_regions(scopes={:?})", scopes);
230 if let ty::ReLateBound(debruijn, br) = r {
231 Self::lookup_bound_region(*debruijn, br, first_free_index, scopes)
237 /// Push a new outlives requirement into our output set of
239 fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) {
240 debug!("push_outlives({:?}: {:?})", sup, sub);
242 self.delegate.push_outlives(sup, sub);
245 /// Relate a projection type and some value type lazily. This will always
246 /// succeed, but we push an additional `ProjectionEq` goal depending
247 /// on the value type:
248 /// - if the value type is any type `T` which is not a projection, we push
249 /// `ProjectionEq(projection = T)`.
250 /// - if the value type is another projection `other_projection`, we create
251 /// a new inference variable `?U` and push the two goals
252 /// `ProjectionEq(projection = ?U)`, `ProjectionEq(other_projection = ?U)`.
253 fn relate_projection_ty(
255 projection_ty: ty::ProjectionTy<'tcx>,
258 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
259 use rustc_span::DUMMY_SP;
261 match *value_ty.kind() {
262 ty::Projection(other_projection_ty) => {
263 let var = self.infcx.next_ty_var(TypeVariableOrigin {
264 kind: TypeVariableOriginKind::MiscVariable,
267 self.relate_projection_ty(projection_ty, var);
268 self.relate_projection_ty(other_projection_ty, var);
272 _ => bug!("should never be invoked with eager normalization"),
276 /// Relate a type inference variable with a value type. This works
277 /// by creating a "generalization" G of the value where all the
278 /// lifetimes are replaced with fresh inference values. This
279 /// genearlization G becomes the value of the inference variable,
280 /// and is then related in turn to the value. So e.g. if you had
281 /// `vid = ?0` and `value = &'a u32`, we might first instantiate
282 /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
283 /// and then relate `&'0 u32` with `&'a u32` (resulting in
284 /// relations between `'0` and `'a`).
286 /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
287 /// -- in other words, it is always a (unresolved) inference
288 /// variable `vid` and a type `ty` that are being related, but the
289 /// vid may appear either as the "a" type or the "b" type,
290 /// depending on where it appears in the tuple. The trait
291 /// `VidValuePair` lets us work with the vid/type while preserving
292 /// the "sidedness" when necessary -- the sidedness is relevant in
293 /// particular for the variance and set of in-scope things.
294 fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
297 ) -> RelateResult<'tcx, Ty<'tcx>> {
298 debug!("relate_ty_var({:?})", pair);
300 let vid = pair.vid();
301 let value_ty = pair.value_ty();
303 // FIXME(invariance) -- this logic assumes invariance, but that is wrong.
304 // This only presently applies to chalk integration, as NLL
305 // doesn't permit type variables to appear on both sides (and
306 // doesn't use lazy norm).
307 match *value_ty.kind() {
308 ty::Infer(ty::TyVar(value_vid)) => {
309 // Two type variables: just equate them.
310 self.infcx.inner.borrow_mut().type_variables().equate(vid, value_vid);
314 ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
315 return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
321 let generalized_ty = self.generalize_value(value_ty, vid)?;
322 debug!("relate_ty_var: generalized_ty = {:?}", generalized_ty);
324 if D::forbid_inference_vars() {
325 // In NLL, we don't have type inference variables
326 // floating around, so we can do this rather imprecise
327 // variant of the occurs-check.
328 assert!(!generalized_ty.has_infer_types_or_consts());
331 self.infcx.inner.borrow_mut().type_variables().instantiate(vid, generalized_ty);
333 // The generalized values we extract from `canonical_var_values` have
334 // been fully instantiated and hence the set of scopes we have
335 // doesn't matter -- just to be sure, put an empty vector
337 let old_a_scopes = std::mem::take(pair.vid_scopes(self));
339 // Relate the generalized kind to the original one.
340 let result = pair.relate_generalized_ty(self, generalized_ty);
342 // Restore the old scopes now.
343 *pair.vid_scopes(self) = old_a_scopes;
345 debug!("relate_ty_var: complete, result = {:?}", result);
349 fn generalize_value<T: Relate<'tcx>>(
353 ) -> RelateResult<'tcx, T> {
354 let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
356 let mut generalizer = TypeGeneralizer {
358 delegate: &mut self.delegate,
359 first_free_index: ty::INNERMOST,
360 ambient_variance: self.ambient_variance,
361 for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
365 generalizer.relate(value, value)
369 /// When we instantiate a inference variable with a value in
370 /// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
371 /// but the ordering may vary (depending on whether the inference
372 /// variable was found on the `a` or `b` sides). Therefore, this trait
373 /// allows us to factor out common code, while preserving the order
375 trait VidValuePair<'tcx>: Debug {
376 /// Extract the inference variable (which could be either the
377 /// first or second part of the tuple).
378 fn vid(&self) -> ty::TyVid;
380 /// Extract the value it is being related to (which will be the
381 /// opposite part of the tuple from the vid).
382 fn value_ty(&self) -> Ty<'tcx>;
384 /// Extract the scopes that apply to whichever side of the tuple
385 /// the vid was found on. See the comment where this is called
386 /// for more details on why we want them.
387 fn vid_scopes<D: TypeRelatingDelegate<'tcx>>(
389 relate: &'r mut TypeRelating<'_, 'tcx, D>,
390 ) -> &'r mut Vec<BoundRegionScope<'tcx>>;
392 /// Given a generalized type G that should replace the vid, relate
393 /// G to the value, putting G on whichever side the vid would have
395 fn relate_generalized_ty<D>(
397 relate: &mut TypeRelating<'_, 'tcx, D>,
398 generalized_ty: Ty<'tcx>,
399 ) -> RelateResult<'tcx, Ty<'tcx>>
401 D: TypeRelatingDelegate<'tcx>;
404 impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
405 fn vid(&self) -> ty::TyVid {
409 fn value_ty(&self) -> Ty<'tcx> {
415 relate: &'r mut TypeRelating<'_, 'tcx, D>,
416 ) -> &'r mut Vec<BoundRegionScope<'tcx>>
418 D: TypeRelatingDelegate<'tcx>,
423 fn relate_generalized_ty<D>(
425 relate: &mut TypeRelating<'_, 'tcx, D>,
426 generalized_ty: Ty<'tcx>,
427 ) -> RelateResult<'tcx, Ty<'tcx>>
429 D: TypeRelatingDelegate<'tcx>,
431 relate.relate(&generalized_ty, &self.value_ty())
435 // In this case, the "vid" is the "b" type.
436 impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
437 fn vid(&self) -> ty::TyVid {
441 fn value_ty(&self) -> Ty<'tcx> {
447 relate: &'r mut TypeRelating<'_, 'tcx, D>,
448 ) -> &'r mut Vec<BoundRegionScope<'tcx>>
450 D: TypeRelatingDelegate<'tcx>,
455 fn relate_generalized_ty<D>(
457 relate: &mut TypeRelating<'_, 'tcx, D>,
458 generalized_ty: Ty<'tcx>,
459 ) -> RelateResult<'tcx, Ty<'tcx>>
461 D: TypeRelatingDelegate<'tcx>,
463 relate.relate(&self.value_ty(), &generalized_ty)
467 impl<D> TypeRelation<'tcx> for TypeRelating<'me, 'tcx, D>
469 D: TypeRelatingDelegate<'tcx>,
471 fn tcx(&self) -> TyCtxt<'tcx> {
475 // FIXME(oli-obk): not sure how to get the correct ParamEnv
476 fn param_env(&self) -> ty::ParamEnv<'tcx> {
477 ty::ParamEnv::empty()
480 fn tag(&self) -> &'static str {
484 fn a_is_expected(&self) -> bool {
488 fn relate_with_variance<T: Relate<'tcx>>(
490 variance: ty::Variance,
493 ) -> RelateResult<'tcx, T> {
494 debug!("relate_with_variance(variance={:?}, a={:?}, b={:?})", variance, a, b);
496 let old_ambient_variance = self.ambient_variance;
497 self.ambient_variance = self.ambient_variance.xform(variance);
499 debug!("relate_with_variance: ambient_variance = {:?}", self.ambient_variance);
501 let r = self.relate(a, b)?;
503 self.ambient_variance = old_ambient_variance;
505 debug!("relate_with_variance: r={:?}", r);
510 fn tys(&mut self, a: Ty<'tcx>, mut b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
511 let a = self.infcx.shallow_resolve(a);
513 if !D::forbid_inference_vars() {
514 b = self.infcx.shallow_resolve(b);
518 // Subtle: if a or b has a bound variable that we are lazilly
519 // substituting, then even if a == b, it could be that the values we
520 // will substitute for those bound variables are *not* the same, and
521 // hence returning `Ok(a)` is incorrect.
522 if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
527 match (a.kind(), b.kind()) {
528 (_, &ty::Infer(ty::TyVar(vid))) => {
529 if D::forbid_inference_vars() {
530 // Forbid inference variables in the RHS.
531 bug!("unexpected inference var {:?}", b)
533 self.relate_ty_var((a, vid))
537 (&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
539 (&ty::Projection(projection_ty), _)
540 if D::normalization() == NormalizationStrategy::Lazy =>
542 Ok(self.relate_projection_ty(projection_ty, b))
545 (_, &ty::Projection(projection_ty))
546 if D::normalization() == NormalizationStrategy::Lazy =>
548 Ok(self.relate_projection_ty(projection_ty, a))
552 debug!("tys(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
554 // Will also handle unification of `IntVar` and `FloatVar`.
555 self.infcx.super_combine_tys(self, a, b)
564 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
565 debug!("regions(a={:?}, b={:?}, variance={:?})", a, b, self.ambient_variance);
567 let v_a = self.replace_bound_region(a, ty::INNERMOST, &self.a_scopes);
568 let v_b = self.replace_bound_region(b, ty::INNERMOST, &self.b_scopes);
570 debug!("regions: v_a = {:?}", v_a);
571 debug!("regions: v_b = {:?}", v_b);
573 if self.ambient_covariance() {
574 // Covariance: a <= b. Hence, `b: a`.
575 self.push_outlives(v_b, v_a);
578 if self.ambient_contravariance() {
579 // Contravariant: b <= a. Hence, `a: b`.
580 self.push_outlives(v_a, v_b);
588 a: &'tcx ty::Const<'tcx>,
589 mut b: &'tcx ty::Const<'tcx>,
590 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
591 let a = self.infcx.shallow_resolve(a);
593 if !D::forbid_inference_vars() {
594 b = self.infcx.shallow_resolve(b);
598 ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
599 // Forbid inference variables in the RHS.
600 bug!("unexpected inference var {:?}", b)
602 // FIXME(invariance): see the related FIXME above.
603 _ => self.infcx.super_combine_consts(self, a, b),
611 ) -> RelateResult<'tcx, ty::Binder<T>>
618 // for<'a> fn(&'a u32) -> &'a u32 <:
619 // fn(&'b u32) -> &'b u32
625 // fn(&'a u32) -> &'a u32 <:
626 // for<'b> fn(&'b u32) -> &'b u32
629 // We therefore proceed as follows:
631 // - Instantiate binders on `b` universally, yielding a universe U1.
632 // - Instantiate binders on `a` existentially in U1.
634 debug!("binders({:?}: {:?}, ambient_variance={:?})", a, b, self.ambient_variance);
636 if let (Some(a), Some(b)) = (a.no_bound_vars(), b.no_bound_vars()) {
637 // Fast path for the common case.
639 return Ok(ty::Binder::bind(a));
642 if self.ambient_covariance() {
643 // Covariance, so we want `for<..> A <: for<..> B` --
644 // therefore we compare any instantiation of A (i.e., A
645 // instantiated with existentials) against every
646 // instantiation of B (i.e., B instantiated with
649 let b_scope = self.create_scope(b, UniversallyQuantified(true));
650 let a_scope = self.create_scope(a, UniversallyQuantified(false));
652 debug!("binders: a_scope = {:?} (existential)", a_scope);
653 debug!("binders: b_scope = {:?} (universal)", b_scope);
655 self.b_scopes.push(b_scope);
656 self.a_scopes.push(a_scope);
658 // Reset the ambient variance to covariant. This is needed
659 // to correctly handle cases like
661 // for<'a> fn(&'a u32, &'a u32) == for<'b, 'c> fn(&'b u32, &'c u32)
663 // Somewhat surprisingly, these two types are actually
664 // **equal**, even though the one on the right looks more
665 // polymorphic. The reason is due to subtyping. To see it,
666 // consider that each function can call the other:
668 // - The left function can call the right with `'b` and
669 // `'c` both equal to `'a`
671 // - The right function can call the left with `'a` set to
672 // `{P}`, where P is the point in the CFG where the call
673 // itself occurs. Note that `'b` and `'c` must both
674 // include P. At the point, the call works because of
675 // subtyping (i.e., `&'b u32 <: &{P} u32`).
676 let variance = std::mem::replace(&mut self.ambient_variance, ty::Variance::Covariant);
678 self.relate(a.skip_binder(), b.skip_binder())?;
680 self.ambient_variance = variance;
682 self.b_scopes.pop().unwrap();
683 self.a_scopes.pop().unwrap();
686 if self.ambient_contravariance() {
687 // Contravariance, so we want `for<..> A :> for<..> B`
688 // -- therefore we compare every instantiation of A (i.e.,
689 // A instantiated with universals) against any
690 // instantiation of B (i.e., B instantiated with
691 // existentials). Opposite of above.
693 let a_scope = self.create_scope(a, UniversallyQuantified(true));
694 let b_scope = self.create_scope(b, UniversallyQuantified(false));
696 debug!("binders: a_scope = {:?} (universal)", a_scope);
697 debug!("binders: b_scope = {:?} (existential)", b_scope);
699 self.a_scopes.push(a_scope);
700 self.b_scopes.push(b_scope);
702 // Reset ambient variance to contravariance. See the
703 // covariant case above for an explanation.
705 std::mem::replace(&mut self.ambient_variance, ty::Variance::Contravariant);
707 self.relate(a.skip_binder(), b.skip_binder())?;
709 self.ambient_variance = variance;
711 self.b_scopes.pop().unwrap();
712 self.a_scopes.pop().unwrap();
719 impl<'tcx, D> ConstEquateRelation<'tcx> for TypeRelating<'_, 'tcx, D>
721 D: TypeRelatingDelegate<'tcx>,
723 fn const_equate_obligation(&mut self, a: &'tcx ty::Const<'tcx>, b: &'tcx ty::Const<'tcx>) {
724 self.delegate.const_equate(a, b);
728 /// When we encounter a binder like `for<..> fn(..)`, we actually have
729 /// to walk the `fn` value to find all the values bound by the `for`
730 /// (these are not explicitly present in the ty representation right
731 /// now). This visitor handles that: it descends the type, tracking
732 /// binder depth, and finds late-bound regions targeting the
733 /// `for<..`>. For each of those, it creates an entry in
734 /// `bound_region_scope`.
735 struct ScopeInstantiator<'me, 'tcx> {
736 next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
737 // The debruijn index of the scope we are instantiating.
738 target_index: ty::DebruijnIndex,
739 bound_region_scope: &'me mut BoundRegionScope<'tcx>,
742 impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
743 fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
744 self.target_index.shift_in(1);
745 t.super_visit_with(self);
746 self.target_index.shift_out(1);
751 fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
752 let ScopeInstantiator { bound_region_scope, next_region, .. } = self;
755 ty::ReLateBound(debruijn, br) if *debruijn == self.target_index => {
756 bound_region_scope.map.entry(*br).or_insert_with(|| next_region(*br));
766 /// The "type generalize" is used when handling inference variables.
768 /// The basic strategy for handling a constraint like `?A <: B` is to
769 /// apply a "generalization strategy" to the type `B` -- this replaces
770 /// all the lifetimes in the type `B` with fresh inference
771 /// variables. (You can read more about the strategy in this [blog
774 /// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
775 /// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
776 /// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
777 /// establishes `'0: 'x` as a constraint.
779 /// As a side-effect of this generalization procedure, we also replace
780 /// all the bound regions that we have traversed with concrete values,
781 /// so that the resulting generalized type is independent from the
784 /// [blog post]: https://is.gd/0hKvIr
785 struct TypeGeneralizer<'me, 'tcx, D>
787 D: TypeRelatingDelegate<'tcx>,
789 infcx: &'me InferCtxt<'me, 'tcx>,
791 delegate: &'me mut D,
793 /// After we generalize this type, we are going to relative it to
794 /// some other type. What will be the variance at this point?
795 ambient_variance: ty::Variance,
797 first_free_index: ty::DebruijnIndex,
799 /// The vid of the type variable that is in the process of being
800 /// instantiated. If we find this within the value we are folding,
801 /// that means we would have created a cyclic value.
802 for_vid_sub_root: ty::TyVid,
804 /// The universe of the type variable that is in the process of being
805 /// instantiated. If we find anything that this universe cannot name,
806 /// we reject the relation.
807 universe: ty::UniverseIndex,
810 impl<D> TypeRelation<'tcx> for TypeGeneralizer<'me, 'tcx, D>
812 D: TypeRelatingDelegate<'tcx>,
814 fn tcx(&self) -> TyCtxt<'tcx> {
818 // FIXME(oli-obk): not sure how to get the correct ParamEnv
819 fn param_env(&self) -> ty::ParamEnv<'tcx> {
820 ty::ParamEnv::empty()
823 fn tag(&self) -> &'static str {
827 fn a_is_expected(&self) -> bool {
831 fn relate_with_variance<T: Relate<'tcx>>(
833 variance: ty::Variance,
836 ) -> RelateResult<'tcx, T> {
838 "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})",
842 let old_ambient_variance = self.ambient_variance;
843 self.ambient_variance = self.ambient_variance.xform(variance);
846 "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}",
847 self.ambient_variance
850 let r = self.relate(a, b)?;
852 self.ambient_variance = old_ambient_variance;
854 debug!("TypeGeneralizer::relate_with_variance: r={:?}", r);
859 fn tys(&mut self, a: Ty<'tcx>, _: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
860 use crate::infer::type_variable::TypeVariableValue;
862 debug!("TypeGeneralizer::tys(a={:?})", a);
865 ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_))
866 if D::forbid_inference_vars() =>
868 bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
871 ty::Infer(ty::TyVar(vid)) => {
872 let mut inner = self.infcx.inner.borrow_mut();
873 let variables = &mut inner.type_variables();
874 let vid = variables.root_var(vid);
875 let sub_vid = variables.sub_root_var(vid);
876 if sub_vid == self.for_vid_sub_root {
877 // If sub-roots are equal, then `for_vid` and
878 // `vid` are related via subtyping.
879 debug!("TypeGeneralizer::tys: occurs check failed");
880 Err(TypeError::Mismatch)
882 match variables.probe(vid) {
883 TypeVariableValue::Known { value: u } => {
887 TypeVariableValue::Unknown { universe: _universe } => {
888 if self.ambient_variance == ty::Bivariant {
889 // FIXME: we may need a WF predicate (related to #54105).
892 let origin = *variables.var_origin(vid);
894 // Replacing with a new variable in the universe `self.universe`,
895 // it will be unified later with the original type variable in
896 // the universe `_universe`.
897 let new_var_id = variables.new_var(self.universe, false, origin);
899 let u = self.tcx().mk_ty_var(new_var_id);
900 debug!("generalize: replacing original vid={:?} with new={:?}", vid, u);
907 ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
908 // No matter what mode we are in,
909 // integer/floating-point types must be equal to be
914 ty::Placeholder(placeholder) => {
915 if self.universe.cannot_name(placeholder.universe) {
917 "TypeGeneralizer::tys: root universe {:?} cannot name\
918 placeholder in universe {:?}",
919 self.universe, placeholder.universe
921 Err(TypeError::Mismatch)
927 _ => relate::super_relate_tys(self, a, a),
935 ) -> RelateResult<'tcx, ty::Region<'tcx>> {
936 debug!("TypeGeneralizer::regions(a={:?})", a);
938 if let ty::ReLateBound(debruijn, _) = a {
939 if *debruijn < self.first_free_index {
944 // For now, we just always create a fresh region variable to
945 // replace all the regions in the source type. In the main
946 // type checker, we special case the case where the ambient
947 // variance is `Invariant` and try to avoid creating a fresh
948 // region variable, but since this comes up so much less in
949 // NLL (only when users use `_` etc) it is much less
952 // As an aside, since these new variables are created in
953 // `self.universe` universe, this also serves to enforce the
954 // universe scoping rules.
956 // FIXME(#54105) -- if the ambient variance is bivariant,
957 // though, we may however need to check well-formedness or
958 // risk a problem like #41677 again.
960 let replacement_region_vid = self.delegate.generalize_existential(self.universe);
962 Ok(replacement_region_vid)
967 a: &'tcx ty::Const<'tcx>,
968 _: &'tcx ty::Const<'tcx>,
969 ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> {
971 ty::ConstKind::Infer(InferConst::Var(_)) if D::forbid_inference_vars() => {
972 bug!("unexpected inference variable encountered in NLL generalization: {:?}", a);
974 ty::ConstKind::Infer(InferConst::Var(vid)) => {
975 let mut inner = self.infcx.inner.borrow_mut();
976 let variable_table = &mut inner.const_unification_table();
977 let var_value = variable_table.probe_value(vid);
978 match var_value.val.known() {
979 Some(u) => self.relate(u, u),
981 let new_var_id = variable_table.new_key(ConstVarValue {
982 origin: var_value.origin,
983 val: ConstVariableValue::Unknown { universe: self.universe },
985 Ok(self.tcx().mk_const_var(new_var_id, a.ty))
989 ty::ConstKind::Unevaluated(..) if self.tcx().lazy_normalization() => Ok(a),
990 _ => relate::super_relate_consts(self, a, a),
998 ) -> RelateResult<'tcx, ty::Binder<T>>
1002 debug!("TypeGeneralizer::binders(a={:?})", a);
1004 self.first_free_index.shift_in(1);
1005 let result = self.relate(a.skip_binder(), a.skip_binder())?;
1006 self.first_free_index.shift_out(1);
1007 Ok(ty::Binder::bind(result))