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