rustc_infer/infer/relate/
generalize.rs

1use std::mem;
2
3use rustc_data_structures::sso::SsoHashMap;
4use rustc_data_structures::stack::ensure_sufficient_stack;
5use rustc_hir::def_id::DefId;
6use rustc_middle::bug;
7use rustc_middle::ty::error::TypeError;
8use rustc_middle::ty::visit::MaxUniverse;
9use rustc_middle::ty::{
10    self, AliasRelationDirection, InferConst, Term, Ty, TyCtxt, TypeVisitable, TypeVisitableExt,
11    TypingMode,
12};
13use rustc_span::Span;
14use tracing::{debug, instrument, warn};
15
16use super::{
17    PredicateEmittingRelation, Relate, RelateResult, StructurallyRelateAliases, TypeRelation,
18};
19use crate::infer::type_variable::TypeVariableValue;
20use crate::infer::unify_key::ConstVariableValue;
21use crate::infer::{InferCtxt, RegionVariableOrigin, relate};
22
23impl<'tcx> InferCtxt<'tcx> {
24    /// The idea is that we should ensure that the type variable `target_vid`
25    /// is equal to, a subtype of, or a supertype of `source_ty`.
26    ///
27    /// For this, we will instantiate `target_vid` with a *generalized* version
28    /// of `source_ty`. Generalization introduces other inference variables wherever
29    /// subtyping could occur. This also does the occurs checks, detecting whether
30    /// instantiating `target_vid` would result in a cyclic type. We eagerly error
31    /// in this case.
32    ///
33    /// This is *not* expected to be used anywhere except for an implementation of
34    /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
35    /// other usecases (i.e. setting the value of a type var).
36    #[instrument(level = "debug", skip(self, relation))]
37    pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
38        &self,
39        relation: &mut R,
40        target_is_expected: bool,
41        target_vid: ty::TyVid,
42        instantiation_variance: ty::Variance,
43        source_ty: Ty<'tcx>,
44    ) -> RelateResult<'tcx, ()> {
45        debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
46
47        // Generalize `source_ty` depending on the current variance. As an example, assume
48        // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
49        // variable.
50        //
51        // Then the `generalized_ty` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
52        // region/type inference variables.
53        //
54        // We then relate `generalized_ty <: source_ty`, adding constraints like `'x: '?2` and
55        // `?1 <: ?3`.
56        let Generalization { value_may_be_infer: generalized_ty, has_unconstrained_ty_var } = self
57            .generalize(
58                relation.span(),
59                relation.structurally_relate_aliases(),
60                target_vid,
61                instantiation_variance,
62                source_ty,
63            )?;
64
65        // Constrain `b_vid` to the generalized type `generalized_ty`.
66        if let &ty::Infer(ty::TyVar(generalized_vid)) = generalized_ty.kind() {
67            self.inner.borrow_mut().type_variables().equate(target_vid, generalized_vid);
68        } else {
69            self.inner.borrow_mut().type_variables().instantiate(target_vid, generalized_ty);
70        }
71
72        // See the comment on `Generalization::has_unconstrained_ty_var`.
73        if has_unconstrained_ty_var {
74            relation.register_predicates([ty::ClauseKind::WellFormed(generalized_ty.into())]);
75        }
76
77        // Finally, relate `generalized_ty` to `source_ty`, as described in previous comment.
78        //
79        // FIXME(#16847): This code is non-ideal because all these subtype
80        // relations wind up attributed to the same spans. We need
81        // to associate causes/spans with each of the relations in
82        // the stack to get this right.
83        if generalized_ty.is_ty_var() {
84            // This happens for cases like `<?0 as Trait>::Assoc == ?0`.
85            // We can't instantiate `?0` here as that would result in a
86            // cyclic type. We instead delay the unification in case
87            // the alias can be normalized to something which does not
88            // mention `?0`.
89            if self.next_trait_solver() {
90                let (lhs, rhs, direction) = match instantiation_variance {
91                    ty::Invariant => {
92                        (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Equate)
93                    }
94                    ty::Covariant => {
95                        (generalized_ty.into(), source_ty.into(), AliasRelationDirection::Subtype)
96                    }
97                    ty::Contravariant => {
98                        (source_ty.into(), generalized_ty.into(), AliasRelationDirection::Subtype)
99                    }
100                    ty::Bivariant => unreachable!("bivariant generalization"),
101                };
102
103                relation.register_predicates([ty::PredicateKind::AliasRelate(lhs, rhs, direction)]);
104            } else {
105                match source_ty.kind() {
106                    &ty::Alias(ty::Projection, data) => {
107                        // FIXME: This does not handle subtyping correctly, we could
108                        // instead create a new inference variable `?normalized_source`, emitting
109                        // `Projection(normalized_source, ?ty_normalized)` and
110                        // `?normalized_source <: generalized_ty`.
111                        relation.register_predicates([ty::ProjectionPredicate {
112                            projection_term: data.into(),
113                            term: generalized_ty.into(),
114                        }]);
115                    }
116                    // The old solver only accepts projection predicates for associated types.
117                    ty::Alias(ty::Inherent | ty::Weak | ty::Opaque, _) => {
118                        return Err(TypeError::CyclicTy(source_ty));
119                    }
120                    _ => bug!("generalized `{source_ty:?} to infer, not an alias"),
121                }
122            }
123        } else {
124            // NOTE: The `instantiation_variance` is not the same variance as
125            // used by the relation. When instantiating `b`, `target_is_expected`
126            // is flipped and the `instantiation_variance` is also flipped. To
127            // constrain the `generalized_ty` while using the original relation,
128            // we therefore only have to flip the arguments.
129            //
130            // ```ignore (not code)
131            // ?a rel B
132            // instantiate_ty_var(?a, B) # expected and variance not flipped
133            // B' rel B
134            // ```
135            // or
136            // ```ignore (not code)
137            // A rel ?b
138            // instantiate_ty_var(?b, A) # expected and variance flipped
139            // A rel A'
140            // ```
141            if target_is_expected {
142                relation.relate(generalized_ty, source_ty)?;
143            } else {
144                debug!("flip relation");
145                relation.relate(source_ty, generalized_ty)?;
146            }
147        }
148
149        Ok(())
150    }
151
152    /// Instantiates the const variable `target_vid` with the given constant.
153    ///
154    /// This also tests if the given const `ct` contains an inference variable which was previously
155    /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
156    /// would result in an infinite type as we continuously replace an inference variable
157    /// in `ct` with `ct` itself.
158    ///
159    /// This is especially important as unevaluated consts use their parents generics.
160    /// They therefore often contain unused args, making these errors far more likely.
161    ///
162    /// A good example of this is the following:
163    ///
164    /// ```compile_fail,E0308
165    /// #![feature(generic_const_exprs)]
166    ///
167    /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
168    ///     todo!()
169    /// }
170    ///
171    /// fn main() {
172    ///     let mut arr = Default::default();
173    ///     arr = bind(arr);
174    /// }
175    /// ```
176    ///
177    /// Here `3 + 4` ends up as `ConstKind::Unevaluated` which uses the generics
178    /// of `fn bind` (meaning that its args contain `N`).
179    ///
180    /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
181    /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
182    ///
183    /// As `3 + 4` contains `N` in its args, this must not succeed.
184    ///
185    /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
186    #[instrument(level = "debug", skip(self, relation))]
187    pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
188        &self,
189        relation: &mut R,
190        target_is_expected: bool,
191        target_vid: ty::ConstVid,
192        source_ct: ty::Const<'tcx>,
193    ) -> RelateResult<'tcx, ()> {
194        // FIXME(generic_const_exprs): Occurs check failures for unevaluated
195        // constants and generic expressions are not yet handled correctly.
196        let Generalization { value_may_be_infer: generalized_ct, has_unconstrained_ty_var } = self
197            .generalize(
198                relation.span(),
199                relation.structurally_relate_aliases(),
200                target_vid,
201                ty::Invariant,
202                source_ct,
203            )?;
204
205        debug_assert!(!generalized_ct.is_ct_infer());
206        if has_unconstrained_ty_var {
207            bug!("unconstrained ty var when generalizing `{source_ct:?}`");
208        }
209
210        self.inner
211            .borrow_mut()
212            .const_unification_table()
213            .union_value(target_vid, ConstVariableValue::Known { value: generalized_ct });
214
215        // Make sure that the order is correct when relating the
216        // generalized const and the source.
217        if target_is_expected {
218            relation.relate_with_variance(
219                ty::Invariant,
220                ty::VarianceDiagInfo::default(),
221                generalized_ct,
222                source_ct,
223            )?;
224        } else {
225            relation.relate_with_variance(
226                ty::Invariant,
227                ty::VarianceDiagInfo::default(),
228                source_ct,
229                generalized_ct,
230            )?;
231        }
232
233        Ok(())
234    }
235
236    /// Attempts to generalize `source_term` for the type variable `target_vid`.
237    /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
238    fn generalize<T: Into<Term<'tcx>> + Relate<TyCtxt<'tcx>>>(
239        &self,
240        span: Span,
241        structurally_relate_aliases: StructurallyRelateAliases,
242        target_vid: impl Into<ty::TermVid>,
243        ambient_variance: ty::Variance,
244        source_term: T,
245    ) -> RelateResult<'tcx, Generalization<T>> {
246        assert!(!source_term.has_escaping_bound_vars());
247        let (for_universe, root_vid) = match target_vid.into() {
248            ty::TermVid::Ty(ty_vid) => {
249                (self.probe_ty_var(ty_vid).unwrap_err(), ty::TermVid::Ty(self.root_var(ty_vid)))
250            }
251            ty::TermVid::Const(ct_vid) => (
252                self.probe_const_var(ct_vid).unwrap_err(),
253                ty::TermVid::Const(
254                    self.inner.borrow_mut().const_unification_table().find(ct_vid).vid,
255                ),
256            ),
257        };
258
259        let mut generalizer = Generalizer {
260            infcx: self,
261            span,
262            structurally_relate_aliases,
263            root_vid,
264            for_universe,
265            root_term: source_term.into(),
266            ambient_variance,
267            in_alias: false,
268            cache: Default::default(),
269            has_unconstrained_ty_var: false,
270        };
271
272        let value_may_be_infer = generalizer.relate(source_term, source_term)?;
273        let has_unconstrained_ty_var = generalizer.has_unconstrained_ty_var;
274        Ok(Generalization { value_may_be_infer, has_unconstrained_ty_var })
275    }
276}
277
278/// The "generalizer" is used when handling inference variables.
279///
280/// The basic strategy for handling a constraint like `?A <: B` is to
281/// apply a "generalization strategy" to the term `B` -- this replaces
282/// all the lifetimes in the term `B` with fresh inference variables.
283/// (You can read more about the strategy in this [blog post].)
284///
285/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
286/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
287/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
288/// establishes `'0: 'x` as a constraint.
289///
290/// [blog post]: https://is.gd/0hKvIr
291struct Generalizer<'me, 'tcx> {
292    infcx: &'me InferCtxt<'tcx>,
293
294    span: Span,
295
296    /// Whether aliases should be related structurally. If not, we have to
297    /// be careful when generalizing aliases.
298    structurally_relate_aliases: StructurallyRelateAliases,
299
300    /// The vid of the type variable that is in the process of being
301    /// instantiated. If we find this within the value we are folding,
302    /// that means we would have created a cyclic value.
303    root_vid: ty::TermVid,
304
305    /// The universe of the type variable that is in the process of being
306    /// instantiated. If we find anything that this universe cannot name,
307    /// we reject the relation.
308    for_universe: ty::UniverseIndex,
309
310    /// The root term (const or type) we're generalizing. Used for cycle errors.
311    root_term: Term<'tcx>,
312
313    /// After we generalize this type, we are going to relate it to
314    /// some other type. What will be the variance at this point?
315    ambient_variance: ty::Variance,
316
317    /// This is set once we're generalizing the arguments of an alias.
318    ///
319    /// This is necessary to correctly handle
320    /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
321    /// hold by either normalizing the outer or the inner associated type.
322    in_alias: bool,
323
324    cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
325
326    /// See the field `has_unconstrained_ty_var` in `Generalization`.
327    has_unconstrained_ty_var: bool,
328}
329
330impl<'tcx> Generalizer<'_, 'tcx> {
331    /// Create an error that corresponds to the term kind in `root_term`
332    fn cyclic_term_error(&self) -> TypeError<'tcx> {
333        match self.root_term.unpack() {
334            ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
335            ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
336        }
337    }
338
339    /// Create a new type variable in the universe of the target when
340    /// generalizing an alias. This has to set `has_unconstrained_ty_var`
341    /// if we're currently in a bivariant context.
342    fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> {
343        self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant;
344        self.infcx.next_ty_var_in_universe(self.span, self.for_universe)
345    }
346
347    /// An occurs check failure inside of an alias does not mean
348    /// that the types definitely don't unify. We may be able
349    /// to normalize the alias after all.
350    ///
351    /// We handle this by lazily equating the alias and generalizing
352    /// it to an inference variable. In the new solver, we always
353    /// generalize to an infer var unless the alias contains escaping
354    /// bound variables.
355    ///
356    /// Correctly handling aliases with escaping bound variables is
357    /// difficult and currently incomplete in two opposite ways:
358    /// - if we get an occurs check failure in the alias, replace it with a new infer var.
359    ///   This causes us to later emit an alias-relate goal and is incomplete in case the
360    ///   alias normalizes to type containing one of the bound variables.
361    /// - if the alias contains an inference variable not nameable by `for_universe`, we
362    ///   continue generalizing the alias. This ends up pulling down the universe of the
363    ///   inference variable and is incomplete in case the alias would normalize to a type
364    ///   which does not mention that inference variable.
365    fn generalize_alias_ty(
366        &mut self,
367        alias: ty::AliasTy<'tcx>,
368    ) -> Result<Ty<'tcx>, TypeError<'tcx>> {
369        // We do not eagerly replace aliases with inference variables if they have
370        // escaping bound vars, see the method comment for details. However, when we
371        // are inside of an alias with escaping bound vars replacing nested aliases
372        // with inference variables can cause incorrect ambiguity.
373        //
374        // cc trait-system-refactor-initiative#110
375        if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
376            return Ok(self.next_ty_var_for_alias());
377        }
378
379        let is_nested_alias = mem::replace(&mut self.in_alias, true);
380        let result = match self.relate(alias, alias) {
381            Ok(alias) => Ok(alias.to_ty(self.cx())),
382            Err(e) => {
383                if is_nested_alias {
384                    return Err(e);
385                } else {
386                    let mut visitor = MaxUniverse::new();
387                    alias.visit_with(&mut visitor);
388                    let infer_replacement_is_complete =
389                        self.for_universe.can_name(visitor.max_universe())
390                            && !alias.has_escaping_bound_vars();
391                    if !infer_replacement_is_complete {
392                        warn!("may incompletely handle alias type: {alias:?}");
393                    }
394
395                    debug!("generalization failure in alias");
396                    Ok(self.next_ty_var_for_alias())
397                }
398            }
399        };
400        self.in_alias = is_nested_alias;
401        result
402    }
403}
404
405impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
406    fn cx(&self) -> TyCtxt<'tcx> {
407        self.infcx.tcx
408    }
409
410    fn relate_item_args(
411        &mut self,
412        item_def_id: DefId,
413        a_arg: ty::GenericArgsRef<'tcx>,
414        b_arg: ty::GenericArgsRef<'tcx>,
415    ) -> RelateResult<'tcx, ty::GenericArgsRef<'tcx>> {
416        if self.ambient_variance == ty::Invariant {
417            // Avoid fetching the variance if we are in an invariant
418            // context; no need, and it can induce dependency cycles
419            // (e.g., #41849).
420            relate::relate_args_invariantly(self, a_arg, b_arg)
421        } else {
422            let tcx = self.cx();
423            let opt_variances = tcx.variances_of(item_def_id);
424            relate::relate_args_with_variances(
425                self,
426                item_def_id,
427                opt_variances,
428                a_arg,
429                b_arg,
430                false,
431            )
432        }
433    }
434
435    #[instrument(level = "debug", skip(self, variance, b), ret)]
436    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
437        &mut self,
438        variance: ty::Variance,
439        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
440        a: T,
441        b: T,
442    ) -> RelateResult<'tcx, T> {
443        let old_ambient_variance = self.ambient_variance;
444        self.ambient_variance = self.ambient_variance.xform(variance);
445        debug!(?self.ambient_variance, "new ambient variance");
446        // Recursive calls to `relate` can overflow the stack. For example a deeper version of
447        // `ui/associated-consts/issue-93775.rs`.
448        let r = ensure_sufficient_stack(|| self.relate(a, b));
449        self.ambient_variance = old_ambient_variance;
450        r
451    }
452
453    #[instrument(level = "debug", skip(self, t2), ret)]
454    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
455        assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
456
457        if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
458            return Ok(result);
459        }
460
461        // Check to see whether the type we are generalizing references
462        // any other type variable related to `vid` via
463        // subtyping. This is basically our "occurs check", preventing
464        // us from creating infinitely sized types.
465        let g = match *t.kind() {
466            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
467                bug!("unexpected infer type: {t}")
468            }
469
470            ty::Infer(ty::TyVar(vid)) => {
471                let mut inner = self.infcx.inner.borrow_mut();
472                let vid = inner.type_variables().root_var(vid);
473                if ty::TermVid::Ty(vid) == self.root_vid {
474                    // If sub-roots are equal, then `root_vid` and
475                    // `vid` are related via subtyping.
476                    Err(self.cyclic_term_error())
477                } else {
478                    let probe = inner.type_variables().probe(vid);
479                    match probe {
480                        TypeVariableValue::Known { value: u } => {
481                            drop(inner);
482                            self.relate(u, u)
483                        }
484                        TypeVariableValue::Unknown { universe } => {
485                            match self.ambient_variance {
486                                // Invariant: no need to make a fresh type variable
487                                // if we can name the universe.
488                                ty::Invariant => {
489                                    if self.for_universe.can_name(universe) {
490                                        return Ok(t);
491                                    }
492                                }
493
494                                // Bivariant: make a fresh var, but remember that
495                                // it is unconstrained. See the comment in
496                                // `Generalization`.
497                                ty::Bivariant => self.has_unconstrained_ty_var = true,
498
499                                // Co/contravariant: this will be
500                                // sufficiently constrained later on.
501                                ty::Covariant | ty::Contravariant => (),
502                            }
503
504                            let origin = inner.type_variables().var_origin(vid);
505                            let new_var_id =
506                                inner.type_variables().new_var(self.for_universe, origin);
507                            // If we're in the new solver and create a new inference
508                            // variable inside of an alias we eagerly constrain that
509                            // inference variable to prevent unexpected ambiguity errors.
510                            //
511                            // This is incomplete as it pulls down the universe of the
512                            // original inference variable, even though the alias could
513                            // normalize to a type which does not refer to that type at
514                            // all. I don't expect this to cause unexpected errors in
515                            // practice.
516                            //
517                            // We only need to do so for type and const variables, as
518                            // region variables do not impact normalization, and will get
519                            // correctly constrained by `AliasRelate` later on.
520                            //
521                            // cc trait-system-refactor-initiative#108
522                            if self.infcx.next_trait_solver()
523                                && !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
524                                && self.in_alias
525                            {
526                                inner.type_variables().equate(vid, new_var_id);
527                            }
528
529                            debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
530                            Ok(Ty::new_var(self.cx(), new_var_id))
531                        }
532                    }
533                }
534            }
535
536            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
537                // No matter what mode we are in,
538                // integer/floating-point types must be equal to be
539                // relatable.
540                Ok(t)
541            }
542
543            ty::Placeholder(placeholder) => {
544                if self.for_universe.can_name(placeholder.universe) {
545                    Ok(t)
546                } else {
547                    debug!(
548                        "root universe {:?} cannot name placeholder in universe {:?}",
549                        self.for_universe, placeholder.universe
550                    );
551                    Err(TypeError::Mismatch)
552                }
553            }
554
555            ty::Alias(_, data) => match self.structurally_relate_aliases {
556                StructurallyRelateAliases::No => self.generalize_alias_ty(data),
557                StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t),
558            },
559
560            _ => relate::structurally_relate_tys(self, t, t),
561        }?;
562
563        self.cache.insert((t, self.ambient_variance, self.in_alias), g);
564        Ok(g)
565    }
566
567    #[instrument(level = "debug", skip(self, r2), ret)]
568    fn regions(
569        &mut self,
570        r: ty::Region<'tcx>,
571        r2: ty::Region<'tcx>,
572    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
573        assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
574
575        match *r {
576            // Never make variables for regions bound within the type itself,
577            // nor for erased regions.
578            ty::ReBound(..) | ty::ReErased => {
579                return Ok(r);
580            }
581
582            // It doesn't really matter for correctness if we generalize ReError,
583            // since we're already on a doomed compilation path.
584            ty::ReError(_) => {
585                return Ok(r);
586            }
587
588            ty::RePlaceholder(..)
589            | ty::ReVar(..)
590            | ty::ReStatic
591            | ty::ReEarlyParam(..)
592            | ty::ReLateParam(..) => {
593                // see common code below
594            }
595        }
596
597        // If we are in an invariant context, we can re-use the region
598        // as is, unless it happens to be in some universe that we
599        // can't name.
600        if let ty::Invariant = self.ambient_variance {
601            let r_universe = self.infcx.universe_of_region(r);
602            if self.for_universe.can_name(r_universe) {
603                return Ok(r);
604            }
605        }
606
607        Ok(self.infcx.next_region_var_in_universe(
608            RegionVariableOrigin::MiscVariable(self.span),
609            self.for_universe,
610        ))
611    }
612
613    #[instrument(level = "debug", skip(self, c2), ret)]
614    fn consts(
615        &mut self,
616        c: ty::Const<'tcx>,
617        c2: ty::Const<'tcx>,
618    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
619        assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
620
621        match c.kind() {
622            ty::ConstKind::Infer(InferConst::Var(vid)) => {
623                // If root const vids are equal, then `root_vid` and
624                // `vid` are related and we'd be inferring an infinitely
625                // deep const.
626                if ty::TermVid::Const(
627                    self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid,
628                ) == self.root_vid
629                {
630                    return Err(self.cyclic_term_error());
631                }
632
633                let mut inner = self.infcx.inner.borrow_mut();
634                let variable_table = &mut inner.const_unification_table();
635                match variable_table.probe_value(vid) {
636                    ConstVariableValue::Known { value: u } => {
637                        drop(inner);
638                        self.relate(u, u)
639                    }
640                    ConstVariableValue::Unknown { origin, universe } => {
641                        if self.for_universe.can_name(universe) {
642                            Ok(c)
643                        } else {
644                            let new_var_id = variable_table
645                                .new_key(ConstVariableValue::Unknown {
646                                    origin,
647                                    universe: self.for_universe,
648                                })
649                                .vid;
650
651                            // See the comment for type inference variables
652                            // for more details.
653                            if self.infcx.next_trait_solver()
654                                && !matches!(self.infcx.typing_mode(), TypingMode::Coherence)
655                                && self.in_alias
656                            {
657                                variable_table.union(vid, new_var_id);
658                            }
659                            Ok(ty::Const::new_var(self.cx(), new_var_id))
660                        }
661                    }
662                }
663            }
664            // FIXME: Unevaluated constants are also not rigid, so the current
665            // approach of always relating them structurally is incomplete.
666            //
667            // FIXME: remove this branch once `structurally_relate_consts` is fully
668            // structural.
669            ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => {
670                let args = self.relate_with_variance(
671                    ty::Invariant,
672                    ty::VarianceDiagInfo::default(),
673                    args,
674                    args,
675                )?;
676                Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args }))
677            }
678            ty::ConstKind::Placeholder(placeholder) => {
679                if self.for_universe.can_name(placeholder.universe) {
680                    Ok(c)
681                } else {
682                    debug!(
683                        "root universe {:?} cannot name placeholder in universe {:?}",
684                        self.for_universe, placeholder.universe
685                    );
686                    Err(TypeError::Mismatch)
687                }
688            }
689            _ => relate::structurally_relate_consts(self, c, c),
690        }
691    }
692
693    #[instrument(level = "debug", skip(self), ret)]
694    fn binders<T>(
695        &mut self,
696        a: ty::Binder<'tcx, T>,
697        _: ty::Binder<'tcx, T>,
698    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
699    where
700        T: Relate<TyCtxt<'tcx>>,
701    {
702        let result = self.relate(a.skip_binder(), a.skip_binder())?;
703        Ok(a.rebind(result))
704    }
705}
706
707/// Result from a generalization operation. This includes
708/// not only the generalized type, but also a bool flag
709/// indicating whether further WF checks are needed.
710#[derive(Debug)]
711struct Generalization<T> {
712    /// When generalizing `<?0 as Trait>::Assoc` or
713    /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
714    /// for `?0` generalization returns an inference
715    /// variable.
716    ///
717    /// This has to be handled wotj care as it can
718    /// otherwise very easily result in infinite
719    /// recursion.
720    pub value_may_be_infer: T,
721
722    /// In general, we do not check whether all types which occur during
723    /// type checking are well-formed. We only check wf of user-provided types
724    /// and when actually using a type, e.g. for method calls.
725    ///
726    /// This means that when subtyping, we may end up with unconstrained
727    /// inference variables if a generalized type has bivariant parameters.
728    /// A parameter may only be bivariant if it is constrained by a projection
729    /// bound in a where-clause. As an example, imagine a type:
730    ///
731    ///     struct Foo<A, B> where A: Iterator<Item = B> {
732    ///         data: A
733    ///     }
734    ///
735    /// here, `A` will be covariant, but `B` is unconstrained.
736    ///
737    /// However, whatever it is, for `Foo` to be WF, it must be equal to `A::Item`.
738    /// If we have an input `Foo<?A, ?B>`, then after generalization we will wind
739    /// up with a type like `Foo<?C, ?D>`. When we enforce `Foo<?A, ?B> <: Foo<?C, ?D>`,
740    /// we will wind up with the requirement that `?A <: ?C`, but no particular
741    /// relationship between `?B` and `?D` (after all, these types may be completely
742    /// different). If we do nothing else, this may mean that `?D` goes unconstrained
743    /// (as in #41677). To avoid this we emit a `WellFormed` obligation in these cases.
744    pub has_unconstrained_ty_var: bool,
745}