Skip to main content

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::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt};
9use rustc_span::Span;
10use tracing::{debug, instrument, warn};
11
12use super::{PredicateEmittingRelation, Relate, RelateResult, TypeRelation};
13use crate::infer::type_variable::TypeVariableValue;
14use crate::infer::unify_key::ConstVariableValue;
15use crate::infer::{InferCtxt, RegionVariableOrigin, relate};
16
17#[derive(#[automatically_derived]
impl ::core::marker::Copy for TermVid { }Copy, #[automatically_derived]
impl ::core::clone::Clone for TermVid {
    #[inline]
    fn clone(&self) -> TermVid {
        let _: ::core::clone::AssertParamIsClone<ty::TyVid>;
        let _: ::core::clone::AssertParamIsClone<ty::ConstVid>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::cmp::Eq for TermVid {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::TyVid>;
        let _: ::core::cmp::AssertParamIsEq<ty::ConstVid>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for TermVid {
    #[inline]
    fn eq(&self, other: &TermVid) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (TermVid::Ty(__self_0), TermVid::Ty(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (TermVid::Const(__self_0), TermVid::Const(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::fmt::Debug for TermVid {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            TermVid::Ty(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ty",
                    &__self_0),
            TermVid::Const(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Const",
                    &__self_0),
        }
    }
}Debug)]
18enum TermVid {
19    Ty(ty::TyVid),
20    Const(ty::ConstVid),
21}
22
23impl From<ty::TyVid> for TermVid {
24    fn from(value: ty::TyVid) -> Self {
25        TermVid::Ty(value)
26    }
27}
28
29impl From<ty::ConstVid> for TermVid {
30    fn from(value: ty::ConstVid) -> Self {
31        TermVid::Const(value)
32    }
33}
34
35impl<'tcx> InferCtxt<'tcx> {
36    /// The idea is that we should ensure that the type variable `target_vid`
37    /// is equal to, a subtype of, or a supertype of `source_ty`.
38    ///
39    /// For this, we will instantiate `target_vid` with a *generalized* version
40    /// of `source_ty`. Generalization introduces other inference variables wherever
41    /// subtyping could occur. This also does the occurs checks, detecting whether
42    /// instantiating `target_vid` would result in a cyclic type. We eagerly error
43    /// in this case.
44    ///
45    /// This is *not* expected to be used anywhere except for an implementation of
46    /// `TypeRelation`. Do not use this, and instead please use `At::eq`, for all
47    /// other usecases (i.e. setting the value of a type var).
48    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("instantiate_ty_var",
                                    "rustc_infer::infer::relate::generalize",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                                    ::tracing_core::__macro_support::Option::Some(48u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_is_expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_is_expected");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("instantiation_variance")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("instantiation_variance");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("source_ty")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("source_ty");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&target_is_expected
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ty)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: RelateResult<'tcx, ()> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if true {
                if !self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()
                    {
                    ::core::panicking::panic("assertion failed: self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown()")
                };
            };
            self.instantiate_var(relation, target_is_expected,
                target_vid.into(), instantiation_variance, source_ty.into())
        }
    }
}#[instrument(level = "debug", skip(self, relation))]
49    pub fn instantiate_ty_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
50        &self,
51        relation: &mut R,
52        target_is_expected: bool,
53        target_vid: ty::TyVid,
54        instantiation_variance: ty::Variance,
55        source_ty: Ty<'tcx>,
56    ) -> RelateResult<'tcx, ()> {
57        debug_assert!(self.inner.borrow_mut().type_variables().probe(target_vid).is_unknown());
58
59        self.instantiate_var(
60            relation,
61            target_is_expected,
62            target_vid.into(),
63            instantiation_variance,
64            source_ty.into(),
65        )
66    }
67
68    /// Instantiates the const variable `target_vid` with the given constant.
69    ///
70    /// This also tests if the given const `ct` contains an inference variable which was previously
71    /// unioned with `target_vid`. If this is the case, inferring `target_vid` to `ct`
72    /// would result in an infinite type as we continuously replace an inference variable
73    /// in `ct` with `ct` itself.
74    ///
75    /// This is especially important as alias consts use their parents generics.
76    /// They therefore often contain unused args, making these errors far more likely.
77    ///
78    /// A good example of this is the following:
79    ///
80    /// ```compile_fail,E0308
81    /// #![feature(generic_const_exprs)]
82    ///
83    /// fn bind<const N: usize>(value: [u8; N]) -> [u8; 3 + 4] {
84    ///     todo!()
85    /// }
86    ///
87    /// fn main() {
88    ///     let mut arr = Default::default();
89    ///     arr = bind(arr);
90    /// }
91    /// ```
92    ///
93    /// Here `3 + 4` ends up as `ConstKind::Alias` which uses the generics
94    /// of `fn bind` (meaning that its args contain `N`).
95    ///
96    /// `bind(arr)` now infers that the type of `arr` must be `[u8; N]`.
97    /// The assignment `arr = bind(arr)` now tries to equate `N` with `3 + 4`.
98    ///
99    /// As `3 + 4` contains `N` in its args, this must not succeed.
100    ///
101    /// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
102    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("instantiate_const_var",
                                    "rustc_infer::infer::relate::generalize",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                                    ::tracing_core::__macro_support::Option::Some(102u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_is_expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_is_expected");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("source_ct")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("source_ct");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&target_is_expected
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_ct)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: RelateResult<'tcx, ()> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if true {
                if !self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
                    {
                    ::core::panicking::panic("assertion failed: self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()")
                };
            };
            self.instantiate_var(relation, target_is_expected,
                target_vid.into(), ty::Invariant, source_ct.into())
        }
    }
}#[instrument(level = "debug", skip(self, relation))]
103    pub(crate) fn instantiate_const_var<R: PredicateEmittingRelation<InferCtxt<'tcx>>>(
104        &self,
105        relation: &mut R,
106        target_is_expected: bool,
107        target_vid: ty::ConstVid,
108        source_ct: ty::Const<'tcx>,
109    ) -> RelateResult<'tcx, ()> {
110        // FIXME(generic_const_exprs): Occurs check failures for alias consts
111        // and generic expressions are not yet handled correctly.
112        debug_assert!(
113            self.inner.borrow_mut().const_unification_table().probe_value(target_vid).is_unknown()
114        );
115
116        self.instantiate_var(
117            relation,
118            target_is_expected,
119            target_vid.into(),
120            ty::Invariant,
121            source_ct.into(),
122        )
123    }
124
125    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("instantiate_var",
                                    "rustc_infer::infer::relate::generalize",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                                    ::tracing_core::__macro_support::Option::Some(125u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_is_expected")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_is_expected");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("target_vid")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("target_vid");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("instantiation_variance")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("instantiation_variance");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("source_term")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("source_term");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&target_is_expected
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_vid)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instantiation_variance)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_term)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: RelateResult<'tcx, ()> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let Generalization { value_may_be_infer: generalized_term } =
                self.generalize(relation.span(), target_vid,
                        instantiation_variance, source_term)?;
            self.union_var_term(target_vid, generalized_term);
            if generalized_term.is_infer() {
                let Some(source_alias) =
                    source_term.to_alias_term() else {
                        ::rustc_middle::util::bug::bug_fmt(format_args!("generalized `{0:?} to infer, not an alias",
                                source_term));
                    };
                if self.next_trait_solver() {
                    if let Some(generalized_ty) = generalized_term.as_type() {
                        match instantiation_variance {
                            ty::Invariant =>
                                relation.register_predicates([ty::ProjectionPredicate {
                                                projection_term: source_alias.into(),
                                                term: generalized_ty.into(),
                                            }]),
                            ty::Covariant => {
                                let new_var = self.next_ty_var(relation.span());
                                relation.register_predicates([ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                                    a_is_expected: !target_is_expected,
                                                    a: new_var,
                                                    b: generalized_ty,
                                                }),
                                            ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
                                                        projection_term: source_alias.into(),
                                                        term: new_var.into(),
                                                    }))]);
                            }
                            ty::Contravariant => {
                                let new_var = self.next_ty_var(relation.span());
                                relation.register_predicates([ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                                    a_is_expected: target_is_expected,
                                                    a: generalized_ty,
                                                    b: new_var,
                                                }),
                                            ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
                                                        projection_term: source_alias.into(),
                                                        term: new_var.into(),
                                                    }))]);
                            }
                            ty::Bivariant => {
                                ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
                                        format_args!("bivariant generalization")));
                            }
                        }
                    } else {
                        if true {
                            {
                                match (&instantiation_variance, &ty::Variance::Invariant) {
                                    (left_val, right_val) => {
                                        if !(*left_val == *right_val) {
                                            let kind = ::core::panicking::AssertKind::Eq;
                                            ::core::panicking::assert_failed(kind, &*left_val,
                                                &*right_val, ::core::option::Option::None);
                                        }
                                    }
                                }
                            };
                        };
                        relation.register_predicates([ty::ProjectionPredicate {
                                        projection_term: source_alias,
                                        term: generalized_term,
                                    }]);
                    }
                } else {
                    match source_alias.kind {
                        ty::AliasTermKind::ProjectionTy { .. } |
                            ty::AliasTermKind::ProjectionConst { .. } => {
                            relation.register_predicates([ty::ProjectionPredicate {
                                            projection_term: source_alias,
                                            term: generalized_term,
                                        }]);
                        }
                        ty::AliasTermKind::InherentTy { .. } |
                            ty::AliasTermKind::FreeTy { .. } |
                            ty::AliasTermKind::OpaqueTy { .. } => {
                            return Err(TypeError::CyclicTy(source_term.expect_type()));
                        }
                        ty::AliasTermKind::InherentConst { .. } |
                            ty::AliasTermKind::FreeConst { .. } |
                            ty::AliasTermKind::AnonConst { .. } => {
                            return Err(TypeError::CyclicConst(source_term.expect_const()));
                        }
                    }
                }
            } else {
                match generalized_term.kind() {
                    ty::TermKind::Ty(_) => {
                        if target_is_expected {
                            relation.relate(generalized_term, source_term)?;
                        } else {
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:264",
                                                    "rustc_infer::infer::relate::generalize",
                                                    ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(264u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                                                    ::tracing_core::field::FieldSet::new(&["message"],
                                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                    ::tracing::metadata::Kind::EVENT)
                                            };
                                        ::tracing::callsite::DefaultCallsite::new(&META)
                                    };
                                let enabled =
                                    ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                            ::tracing::Level::DEBUG <=
                                                ::tracing::level_filters::LevelFilter::current() &&
                                        {
                                            let interest = __CALLSITE.interest();
                                            !interest.is_never() &&
                                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                    interest)
                                        };
                                if enabled {
                                    (|value_set: ::tracing::field::ValueSet|
                                                {
                                                    let meta = __CALLSITE.metadata();
                                                    ::tracing::Event::dispatch(meta, &value_set);
                                                    ;
                                                })({
                                            #[allow(unused_imports)]
                                            use ::tracing::field::{debug, display, Value};
                                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("flip relation")
                                                                        as &dyn ::tracing::field::Value))])
                                        });
                                } else { ; }
                            };
                            relation.relate(source_term, generalized_term)?;
                        }
                    }
                    ty::TermKind::Const(_) => {
                        if target_is_expected {
                            relation.relate_with_variance(ty::Invariant,
                                    ty::VarianceDiagInfo::default(), generalized_term,
                                    source_term)?;
                        } else {
                            relation.relate_with_variance(ty::Invariant,
                                    ty::VarianceDiagInfo::default(), source_term,
                                    generalized_term)?;
                        }
                    }
                }
            }
            Ok(())
        }
    }
}#[instrument(level = "debug", skip(self, relation))]
126    fn instantiate_var<R: PredicateEmittingRelation<Self>>(
127        &self,
128        relation: &mut R,
129        target_is_expected: bool,
130        target_vid: TermVid,
131        instantiation_variance: ty::Variance,
132        source_term: Term<'tcx>,
133    ) -> RelateResult<'tcx, ()> {
134        // Generalize `source_term` depending on the current variance. As an example, assume
135        // `?target <: &'x ?1`, where `'x` is some free region and `?1` is an inference
136        // variable.
137        //
138        // Then the `generalized_term` would be `&'?2 ?3`, where `'?2` and `?3` are fresh
139        // region/type inference variables.
140        //
141        // We then relate `generalized_term <: source_term`, adding constraints like `'x: '?2` and
142        // `?1 <: ?3`.
143        let Generalization { value_may_be_infer: generalized_term } =
144            self.generalize(relation.span(), target_vid, instantiation_variance, source_term)?;
145
146        // Constrain `b_vid` to the generalized type `generalized_term`.
147        self.union_var_term(target_vid, generalized_term);
148
149        // Finally, relate `generalized_term` to `source_term`, as described in previous comment.
150        //
151        // FIXME(#16847): This code is non-ideal because all these subtype
152        // relations wind up attributed to the same spans. We need
153        // to associate causes/spans with each of the relations in
154        // the stack to get this right.
155        if generalized_term.is_infer() {
156            // This happens for cases like `<?0 as Trait>::Assoc == ?0`.
157            // We can't instantiate `?0` here as that would result in a
158            // cyclic type. We instead delay the unification in case
159            // the alias can be normalized to something which does not
160            // mention `?0`.
161            let Some(source_alias) = source_term.to_alias_term() else {
162                bug!("generalized `{source_term:?} to infer, not an alias");
163            };
164            if self.next_trait_solver() {
165                if let Some(generalized_ty) = generalized_term.as_type() {
166                    match instantiation_variance {
167                        ty::Invariant => relation.register_predicates([ty::ProjectionPredicate {
168                            projection_term: source_alias.into(),
169                            term: generalized_ty.into(),
170                        }]),
171                        ty::Covariant => {
172                            // Generate a new var, then do:
173                            // `source_alias == ?A && ?A <: generalized_ty`
174                            let new_var = self.next_ty_var(relation.span());
175                            relation.register_predicates([
176                                ty::PredicateKind::Subtype(ty::SubtypePredicate {
177                                    a_is_expected: !target_is_expected,
178                                    a: new_var,
179                                    b: generalized_ty,
180                                }),
181                                ty::PredicateKind::Clause(ty::ClauseKind::Projection(
182                                    ty::ProjectionPredicate {
183                                        projection_term: source_alias.into(),
184                                        term: new_var.into(),
185                                    },
186                                )),
187                            ]);
188                        }
189                        ty::Contravariant => {
190                            // a :> b is b <: a
191                            let new_var = self.next_ty_var(relation.span());
192                            relation.register_predicates([
193                                ty::PredicateKind::Subtype(ty::SubtypePredicate {
194                                    a_is_expected: target_is_expected,
195                                    a: generalized_ty,
196                                    b: new_var,
197                                }),
198                                ty::PredicateKind::Clause(ty::ClauseKind::Projection(
199                                    ty::ProjectionPredicate {
200                                        projection_term: source_alias.into(),
201                                        term: new_var.into(),
202                                    },
203                                )),
204                            ]);
205                        }
206                        ty::Bivariant => unreachable!("bivariant generalization"),
207                    }
208                } else {
209                    debug_assert_eq!(instantiation_variance, ty::Variance::Invariant);
210                    relation.register_predicates([ty::ProjectionPredicate {
211                        projection_term: source_alias,
212                        term: generalized_term,
213                    }]);
214                }
215            } else {
216                match source_alias.kind {
217                    ty::AliasTermKind::ProjectionTy { .. }
218                    | ty::AliasTermKind::ProjectionConst { .. } => {
219                        // FIXME: This does not handle subtyping correctly, we could
220                        // instead create a new inference variable `?normalized_source`, emitting
221                        // `Projection(normalized_source, ?ty_normalized)` and
222                        // `?normalized_source <: generalized_term`.
223                        relation.register_predicates([ty::ProjectionPredicate {
224                            projection_term: source_alias,
225                            term: generalized_term,
226                        }]);
227                    }
228                    // The old solver only accepts projection predicates for associated types.
229                    ty::AliasTermKind::InherentTy { .. }
230                    | ty::AliasTermKind::FreeTy { .. }
231                    | ty::AliasTermKind::OpaqueTy { .. } => {
232                        return Err(TypeError::CyclicTy(source_term.expect_type()));
233                    }
234                    ty::AliasTermKind::InherentConst { .. }
235                    | ty::AliasTermKind::FreeConst { .. }
236                    | ty::AliasTermKind::AnonConst { .. } => {
237                        return Err(TypeError::CyclicConst(source_term.expect_const()));
238                    }
239                }
240            }
241        } else {
242            // NOTE: The `instantiation_variance` is not the same variance as
243            // used by the relation. When instantiating `b`, `target_is_expected`
244            // is flipped and the `instantiation_variance` is also flipped. To
245            // constrain the `generalized_term` while using the original relation,
246            // we therefore only have to flip the arguments.
247            //
248            // ```ignore (not code)
249            // ?a rel B
250            // instantiate_ty_var(?a, B) # expected and variance not flipped
251            // B' rel B
252            // ```
253            // or
254            // ```ignore (not code)
255            // A rel ?b
256            // instantiate_ty_var(?b, A) # expected and variance flipped
257            // A rel A'
258            // ```
259            match generalized_term.kind() {
260                ty::TermKind::Ty(_) => {
261                    if target_is_expected {
262                        relation.relate(generalized_term, source_term)?;
263                    } else {
264                        debug!("flip relation");
265                        relation.relate(source_term, generalized_term)?;
266                    }
267                }
268                ty::TermKind::Const(_) => {
269                    // Override consts to always be invariant
270                    if target_is_expected {
271                        relation.relate_with_variance(
272                            ty::Invariant,
273                            ty::VarianceDiagInfo::default(),
274                            generalized_term,
275                            source_term,
276                        )?;
277                    } else {
278                        relation.relate_with_variance(
279                            ty::Invariant,
280                            ty::VarianceDiagInfo::default(),
281                            source_term,
282                            generalized_term,
283                        )?;
284                    }
285                }
286            }
287        }
288
289        Ok(())
290    }
291
292    /// This is a thin wrapper around inserting into the var tables. You probably want
293    /// [`Self::instantiate_var`] instead, which calls this method.
294    fn union_var_term(&self, l: TermVid, r: ty::Term<'tcx>) {
295        match (l, r.kind()) {
296            (TermVid::Ty(l), ty::TermKind::Ty(r)) => {
297                if let Some(r) = r.ty_vid() {
298                    self.inner.borrow_mut().type_variables().equate(l, r)
299                } else {
300                    // Ideally, we put this assert into `type_variables().instantiate()`.
301                    // But we can't pass the infcx into it as the infcx is already
302                    // mutably borrowed.
303                    if true {
    if !self.try_resolve_ty_var(l).unwrap_err().can_name(ty::max_universe(self,
                    r)) {
        ::core::panicking::panic("assertion failed: self.try_resolve_ty_var(l).unwrap_err().can_name(ty::max_universe(self, r))")
    };
};debug_assert!(
304                        self.try_resolve_ty_var(l).unwrap_err().can_name(ty::max_universe(self, r))
305                    );
306                    self.inner.borrow_mut().type_variables().instantiate(l, r)
307                }
308            }
309            (TermVid::Const(l), ty::TermKind::Const(r)) => {
310                if let Some(r) = r.ct_vid() {
311                    self.inner.borrow_mut().const_unification_table().union(l, r)
312                } else {
313                    if true {
    if !self.try_resolve_const_var(l).unwrap_err().can_name(ty::max_universe(self,
                    r)) {
        ::core::panicking::panic("assertion failed: self.try_resolve_const_var(l).unwrap_err().can_name(ty::max_universe(self, r))")
    };
};debug_assert!(
314                        self.try_resolve_const_var(l)
315                            .unwrap_err()
316                            .can_name(ty::max_universe(self, r))
317                    );
318                    self.inner
319                        .borrow_mut()
320                        .const_unification_table()
321                        .union_value(l, ConstVariableValue::Known { value: r })
322                }
323            }
324            _ => ::rustc_middle::util::bug::bug_fmt(format_args!("mismatched term kinds in generalize: {0:?}, {1:?}",
        l, r))bug!("mismatched term kinds in generalize: {l:?}, {r:?}"),
325        }
326    }
327
328    /// Attempts to generalize `source_term` for the type variable `target_vid`.
329    /// This checks for cycles -- that is, whether `source_term` references `target_vid`.
330    fn generalize(
331        &self,
332        span: Span,
333        target_vid: TermVid,
334        ambient_variance: ty::Variance,
335        source_term: Term<'tcx>,
336    ) -> RelateResult<'tcx, Generalization<Term<'tcx>>> {
337        if !!source_term.has_escaping_bound_vars() {
    ::core::panicking::panic("assertion failed: !source_term.has_escaping_bound_vars()")
};assert!(!source_term.has_escaping_bound_vars());
338        let (for_universe, root_vid) = match target_vid {
339            TermVid::Ty(ty_vid) => {
340                (self.try_resolve_ty_var(ty_vid).unwrap_err(), TermVid::Ty(self.root_var(ty_vid)))
341            }
342            TermVid::Const(ct_vid) => (
343                self.try_resolve_const_var(ct_vid).unwrap_err(),
344                TermVid::Const(self.inner.borrow_mut().const_unification_table().find(ct_vid).vid),
345            ),
346        };
347
348        let mut generalizer = Generalizer {
349            infcx: self,
350            span,
351            root_vid,
352            for_universe,
353            root_term: source_term,
354            ambient_variance,
355            in_alias: false,
356            cache: Default::default(),
357        };
358
359        let value_may_be_infer = generalizer.relate(source_term, source_term)?;
360        Ok(Generalization { value_may_be_infer })
361    }
362}
363
364/// The "generalizer" is used when handling inference variables.
365///
366/// The basic strategy for handling a constraint like `?A <: B` is to
367/// apply a "generalization strategy" to the term `B` -- this replaces
368/// all the lifetimes in the term `B` with fresh inference variables.
369/// (You can read more about the strategy in this [blog post].)
370///
371/// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
372/// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
373/// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
374/// establishes `'0: 'x` as a constraint.
375///
376/// [blog post]: https://is.gd/0hKvIr
377struct Generalizer<'me, 'tcx> {
378    infcx: &'me InferCtxt<'tcx>,
379
380    span: Span,
381
382    /// The vid of the type variable that is in the process of being
383    /// instantiated. If we find this within the value we are folding,
384    /// that means we would have created a cyclic value.
385    root_vid: TermVid,
386
387    /// The universe of the type variable that is in the process of being
388    /// instantiated. If we find anything that this universe cannot name,
389    /// we reject the relation.
390    for_universe: ty::UniverseIndex,
391
392    /// The root term (const or type) we're generalizing. Used for cycle errors.
393    root_term: Term<'tcx>,
394
395    /// After we generalize this type, we are going to relate it to
396    /// some other type. What will be the variance at this point?
397    ambient_variance: ty::Variance,
398
399    /// This is set once we're generalizing the arguments of an alias.
400    ///
401    /// This is necessary to correctly handle
402    /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
403    /// hold by either normalizing the outer or the inner associated type.
404    in_alias: bool,
405
406    cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>,
407}
408
409impl<'tcx> Generalizer<'_, 'tcx> {
410    /// Create an error that corresponds to the term kind in `root_term`
411    fn cyclic_term_error(&self) -> TypeError<'tcx> {
412        match self.root_term.kind() {
413            ty::TermKind::Ty(ty) => TypeError::CyclicTy(ty),
414            ty::TermKind::Const(ct) => TypeError::CyclicConst(ct),
415        }
416    }
417
418    /// Create a new type variable in the universe of the target when
419    /// generalizing an alias.
420    fn next_var_for_alias_of_kind(&self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> {
421        if alias.kind.is_type() {
422            self.infcx.next_ty_var_in_universe(self.span, self.for_universe).into()
423        } else {
424            self.infcx.next_const_var_in_universe(self.span, self.for_universe).into()
425        }
426    }
427
428    /// We only handle potentially normalizable aliases via this method. For rigid alias,
429    /// we always generalize structurally.
430    ///
431    /// An occurs check failure inside of an alias does not mean
432    /// that the types definitely don't unify. We may be able
433    /// to normalize the alias after all.
434    ///
435    /// We handle this by lazily equating the normalizable alias
436    /// and generalizing it to an inference variable. In the new solver,
437    /// we always generalize to an infer var unless the alias contains escaping
438    /// bound variables.
439    ///
440    /// Correctly handling aliases with escaping bound variables is
441    /// difficult and currently incomplete in two opposite ways:
442    /// - if we get an occurs check failure in the alias, replace it with a new infer var.
443    ///   This causes us to later emit an alias-relate goal and is incomplete in case the
444    ///   alias normalizes to type containing one of the bound variables.
445    /// - if the alias contains an inference variable not nameable by `for_universe`, we
446    ///   continue generalizing the alias. This ends up pulling down the universe of the
447    ///   inference variable and is incomplete in case the alias would normalize to a type
448    ///   which does not mention that inference variable.
449    fn generalize_alias_term(
450        &mut self,
451        alias: ty::AliasTerm<'tcx>,
452    ) -> Result<Term<'tcx>, TypeError<'tcx>> {
453        // We do not eagerly replace aliases with inference variables if they have
454        // escaping bound vars, see the method comment for details. However, when we
455        // are inside of an alias with escaping bound vars replacing nested aliases
456        // with inference variables can cause incorrect ambiguity.
457        //
458        // cc trait-system-refactor-initiative#110
459        if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias {
460            return Ok(self.next_var_for_alias_of_kind(alias));
461        }
462
463        let is_nested_alias = mem::replace(&mut self.in_alias, true);
464        let result = match self.relate(alias, alias) {
465            Ok(alias) => Ok(alias.to_term(self.cx(), ty::IsRigid::No)),
466            Err(e) => {
467                if is_nested_alias {
468                    return Err(e);
469                } else {
470                    let alias_max_universe = ty::max_universe_of_placeholders(self.infcx, alias);
471                    let infer_replacement_is_complete =
472                        self.for_universe.can_name(alias_max_universe)
473                            && !alias.has_escaping_bound_vars();
474                    if !infer_replacement_is_complete {
475                        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:475",
                        "rustc_infer::infer::relate::generalize",
                        ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                        ::tracing_core::__macro_support::Option::Some(475u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("may incompletely handle alias type: {0:?}",
                                                    alias) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};warn!("may incompletely handle alias type: {alias:?}");
476                    }
477
478                    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/relate/generalize.rs:478",
                        "rustc_infer::infer::relate::generalize",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/generalize.rs"),
                        ::tracing_core::__macro_support::Option::Some(478u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::generalize"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("generalization failure in alias")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("generalization failure in alias");
479                    Ok(self.next_var_for_alias_of_kind(alias))
480                }
481            }
482        };
483        self.in_alias = is_nested_alias;
484        result
485    }
486}
487
488impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
489    fn cx(&self) -> TyCtxt<'tcx> {
490        self.infcx.tcx
491    }
492
493    fn relate_ty_args(
494        &mut self,
495        a_ty: Ty<'tcx>,
496        _: Ty<'tcx>,
497        def_id: DefId,
498        a_args: ty::GenericArgsRef<'tcx>,
499        b_args: ty::GenericArgsRef<'tcx>,
500        mk: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
501    ) -> RelateResult<'tcx, Ty<'tcx>> {
502        let args = if self.ambient_variance == ty::Invariant {
503            // Avoid fetching the variance if we are in an invariant
504            // context; no need, and it can induce dependency cycles
505            // (e.g., #41849).
506            relate::relate_args_invariantly(self, a_args, b_args)
507        } else {
508            let tcx = self.cx();
509            let variances = tcx.variances_of(def_id);
510            relate::relate_args_with_variances(self, variances, a_args, b_args)
511        }?;
512        if args == a_args { Ok(a_ty) } else { Ok(mk(args)) }
513    }
514
515    x;#[instrument(level = "debug", skip(self, variance, b), ret)]
516    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
517        &mut self,
518        variance: ty::Variance,
519        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
520        a: T,
521        b: T,
522    ) -> RelateResult<'tcx, T> {
523        let old_ambient_variance = self.ambient_variance;
524        self.ambient_variance = self.ambient_variance.xform(variance);
525        debug!(?self.ambient_variance, "new ambient variance");
526        // Recursive calls to `relate` can overflow the stack. For example a deeper version of
527        // `ui/associated-consts/issue-93775.rs`.
528        let r = ensure_sufficient_stack(|| self.relate(a, b));
529        self.ambient_variance = old_ambient_variance;
530        r
531    }
532
533    x;#[instrument(level = "debug", skip(self, t2), ret)]
534    fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
535        assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
536
537        if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) {
538            return Ok(result);
539        }
540
541        // Check to see whether the type we are generalizing references
542        // any other type variable related to `vid` via
543        // subtyping. This is basically our "occurs check", preventing
544        // us from creating infinitely sized types.
545        let g = match *t.kind() {
546            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
547                bug!("unexpected infer type: {t}")
548            }
549
550            ty::Infer(ty::TyVar(vid)) => {
551                let mut inner = self.infcx.inner.borrow_mut();
552                let vid = inner.type_variables().root_var(vid);
553                if TermVid::Ty(vid) == self.root_vid {
554                    // If sub-roots are equal, then `root_vid` and
555                    // `vid` are related via subtyping.
556                    Err(self.cyclic_term_error())
557                } else {
558                    let probe = inner.type_variables().probe(vid);
559                    match probe {
560                        TypeVariableValue::Known { value: u } => {
561                            drop(inner);
562                            self.relate(u, u)
563                        }
564                        TypeVariableValue::Unknown { universe } => {
565                            match self.ambient_variance {
566                                // Invariant: no need to make a fresh type variable
567                                // if we can name the universe.
568                                ty::Invariant => {
569                                    if self.for_universe.can_name(universe) {
570                                        return Ok(t);
571                                    }
572                                }
573
574                                // We do need a fresh type variable otherwise.
575                                ty::Bivariant | ty::Covariant | ty::Contravariant => (),
576                            }
577
578                            let origin = inner.type_variables().var_origin(vid);
579                            let new_var_id =
580                                inner.type_variables().new_var(self.for_universe, origin);
581                            // Record that `vid` and `new_var_id` have to be subtypes
582                            // of each other. This is currently only used for diagnostics.
583                            // To see why, see the docs in the `type_variables` module.
584                            inner.type_variables().sub_unify(vid, new_var_id);
585                            // If we're in the new solver and create a new inference
586                            // variable inside of an alias we eagerly constrain that
587                            // inference variable to prevent unexpected ambiguity errors.
588                            //
589                            // This is incomplete as it pulls down the universe of the
590                            // original inference variable, even though the alias could
591                            // normalize to a type which does not refer to that type at
592                            // all. I don't expect this to cause unexpected errors in
593                            // practice.
594                            //
595                            // We only need to do so for type and const variables, as
596                            // region variables do not impact normalization, and will get
597                            // correctly constrained by `AliasRelate` later on.
598                            //
599                            // cc trait-system-refactor-initiative#108
600                            if self.infcx.next_trait_solver()
601                                && !self.infcx.typing_mode_raw().is_coherence()
602                                && self.in_alias
603                            {
604                                inner.type_variables().equate(vid, new_var_id);
605                            }
606
607                            debug!("replacing original vid={:?} with new={:?}", vid, new_var_id);
608                            Ok(Ty::new_var(self.cx(), new_var_id))
609                        }
610                    }
611                }
612            }
613
614            ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) => {
615                // No matter what mode we are in,
616                // integer/floating-point types must be equal to be
617                // relatable.
618                Ok(t)
619            }
620
621            ty::Placeholder(placeholder) => {
622                if self.for_universe.can_name(placeholder.universe) {
623                    Ok(t)
624                } else {
625                    debug!(
626                        "root universe {:?} cannot name placeholder in universe {:?}",
627                        self.for_universe, placeholder.universe
628                    );
629                    Err(TypeError::Mismatch)
630                }
631            }
632
633            // We only need to be careful with potentially normalizeable
634            // aliases here. See `generalize_alias_term` for more information.
635            ty::Alias(ty::IsRigid::No, data) => {
636                self.generalize_alias_term(data.into()).map(|v| v.expect_type())
637            }
638
639            _ => relate::structurally_relate_tys(self, t, t),
640        }?;
641
642        self.cache.insert((t, self.ambient_variance, self.in_alias), g);
643        Ok(g)
644    }
645
646    x;#[instrument(level = "debug", skip(self, r2), ret)]
647    fn regions(
648        &mut self,
649        r: ty::Region<'tcx>,
650        r2: ty::Region<'tcx>,
651    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
652        assert_eq!(r, r2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
653
654        match r.kind() {
655            // Never make variables for regions bound within the type itself,
656            // nor for erased regions.
657            ty::ReBound(..) | ty::ReErased => {
658                return Ok(r);
659            }
660
661            // It doesn't really matter for correctness if we generalize ReError,
662            // since we're already on a doomed compilation path.
663            ty::ReError(_) => {
664                return Ok(r);
665            }
666
667            ty::RePlaceholder(..)
668            | ty::ReVar(..)
669            | ty::ReStatic
670            | ty::ReEarlyParam(..)
671            | ty::ReLateParam(..) => {
672                // see common code below
673            }
674        }
675
676        // If we are in an invariant context, we can re-use the region
677        // as is, unless it happens to be in some universe that we
678        // can't name.
679        if let ty::Invariant = self.ambient_variance {
680            let r_universe = self.infcx.universe_of_region(r);
681            if self.for_universe.can_name(r_universe) {
682                return Ok(r);
683            }
684        }
685
686        Ok(self
687            .infcx
688            .next_region_var_in_universe(RegionVariableOrigin::Misc(self.span), self.for_universe))
689    }
690
691    x;#[instrument(level = "debug", skip(self, c2), ret)]
692    fn consts(
693        &mut self,
694        c: ty::Const<'tcx>,
695        c2: ty::Const<'tcx>,
696    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
697        let tcx = self.cx();
698        assert_eq!(c, c2); // we are misusing TypeRelation here; both LHS and RHS ought to be ==
699
700        match c.kind() {
701            ty::ConstKind::Infer(InferConst::Var(vid)) => {
702                // If root const vids are equal, then `root_vid` and
703                // `vid` are related and we'd be inferring an infinitely
704                // deep const.
705                if TermVid::Const(
706                    self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid,
707                ) == self.root_vid
708                {
709                    return Err(self.cyclic_term_error());
710                }
711
712                let mut inner = self.infcx.inner.borrow_mut();
713                let variable_table = &mut inner.const_unification_table();
714                match variable_table.probe_value(vid) {
715                    ConstVariableValue::Known { value: u } => {
716                        drop(inner);
717                        self.relate(u, u)
718                    }
719                    ConstVariableValue::Unknown { origin, universe } => {
720                        if self.for_universe.can_name(universe) {
721                            Ok(c)
722                        } else {
723                            let new_var_id = variable_table
724                                .new_key(ConstVariableValue::Unknown {
725                                    origin,
726                                    universe: self.for_universe,
727                                })
728                                .vid;
729
730                            // See the comment for type inference variables
731                            // for more details.
732                            if self.infcx.next_trait_solver()
733                                && !self.infcx.typing_mode_raw().is_coherence()
734                                && self.in_alias
735                            {
736                                variable_table.union(vid, new_var_id);
737                            }
738                            Ok(ty::Const::new_var(tcx, new_var_id))
739                        }
740                    }
741                }
742            }
743            // FIXME: Alias consts are also not rigid, so the current
744            // approach of always relating them structurally is incomplete.
745            //
746            // FIXME: replace the `else` branch with
747            // `structurally_relate_consts` once it is fully structural.
748            //
749            // We only need to be careful with potentially normalizeable
750            // aliases here. See `generalize_alias_term` for more information.
751            ty::ConstKind::Alias(ty::IsRigid::No, alias_const) => {
752                // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
753                // path), as doing this new No path breaks some GCE things. I expect GCE to be
754                // ripped out soon so this shouldn't matter soon.
755                if self.infcx.next_trait_solver() || !tcx.features().generic_const_exprs() {
756                    self.generalize_alias_term(alias_const.into()).map(|v| v.expect_const())
757                } else {
758                    let ty::AliasConst { kind, args, .. } = alias_const;
759                    let args = self.relate_with_variance(
760                        ty::Invariant,
761                        ty::VarianceDiagInfo::default(),
762                        args,
763                        args,
764                    )?;
765                    Ok(ty::Const::new_alias(
766                        tcx,
767                        ty::IsRigid::No,
768                        ty::AliasConst::new(tcx, kind, args),
769                    ))
770                }
771            }
772            ty::ConstKind::Placeholder(placeholder) => {
773                if self.for_universe.can_name(placeholder.universe) {
774                    Ok(c)
775                } else {
776                    debug!(
777                        "root universe {:?} cannot name placeholder in universe {:?}",
778                        self.for_universe, placeholder.universe
779                    );
780                    Err(TypeError::Mismatch)
781                }
782            }
783            _ => relate::structurally_relate_consts(self, c, c),
784        }
785    }
786
787    x;#[instrument(level = "debug", skip(self), ret)]
788    fn binders<T>(
789        &mut self,
790        a: ty::Binder<'tcx, T>,
791        _: ty::Binder<'tcx, T>,
792    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
793    where
794        T: Relate<TyCtxt<'tcx>>,
795    {
796        let result = self.relate(a.skip_binder(), a.skip_binder())?;
797        Ok(a.rebind(result))
798    }
799}
800
801/// Result from a generalization operation. This includes
802/// not only the generalized type, but also a bool flag
803/// indicating whether further WF checks are needed.
804#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for Generalization<T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "Generalization", "value_may_be_infer", &&self.value_may_be_infer)
    }
}Debug)]
805struct Generalization<T> {
806    /// When generalizing `<?0 as Trait>::Assoc` or
807    /// `<T as Bar<<?0 as Foo>::Assoc>>::Assoc`
808    /// for `?0` generalization returns an inference
809    /// variable.
810    ///
811    /// This has to be handled with care as it can
812    /// otherwise very easily result in infinite
813    /// recursion.
814    pub value_may_be_infer: T,
815}