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