Skip to main content

hir_ty/next_solver/infer/relate/
generalize.rs

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