Skip to main content

rustc_infer/infer/relate/
type_relating.rs

1use rustc_hir::def_id::DefId;
2use rustc_middle::traits::solve::Goal;
3use rustc_middle::ty::relate::combine::{combine_ty_args, super_combine_consts, super_combine_tys};
4use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation, relate_args_invariantly};
5use rustc_middle::ty::{self, DelayedSet, Ty, TyCtxt, TyVar, TypeVisitableExt};
6use rustc_span::Span;
7use tracing::{debug, instrument};
8
9use crate::infer::BoundRegionConversionTime::HigherRankedType;
10use crate::infer::relate::{PredicateEmittingRelation, StructurallyRelateAliases};
11use crate::infer::{DefineOpaqueTypes, InferCtxt, SubregionOrigin, TypeTrace};
12use crate::traits::{Obligation, PredicateObligations};
13
14/// Enforce that `a` is equal to or a subtype of `b`.
15pub(crate) struct TypeRelating<'infcx, 'tcx> {
16    infcx: &'infcx InferCtxt<'tcx>,
17
18    // Immutable fields
19    trace: TypeTrace<'tcx>,
20    param_env: ty::ParamEnv<'tcx>,
21    define_opaque_types: DefineOpaqueTypes,
22
23    // Mutable fields.
24    ambient_variance: ty::Variance,
25    obligations: PredicateObligations<'tcx>,
26    /// The cache only tracks the `ambient_variance` as it's the
27    /// only field which is mutable and which meaningfully changes
28    /// the result when relating types.
29    ///
30    /// The cache does not track whether the state of the
31    /// `InferCtxt` has been changed or whether we've added any
32    /// obligations to `self.goals`. Whether a goal is added
33    /// once or multiple times is not really meaningful.
34    ///
35    /// Changes in the inference state may delay some type inference to
36    /// the next fulfillment loop. Given that this loop is already
37    /// necessary, this is also not a meaningful change. Consider
38    /// the following three relations:
39    /// ```text
40    /// Vec<?0> sub Vec<?1>
41    /// ?0 eq u32
42    /// Vec<?0> sub Vec<?1>
43    /// ```
44    /// Without a cache, the second `Vec<?0> sub Vec<?1>` would eagerly
45    /// constrain `?1` to `u32`. When using the cache entry from the
46    /// first time we've related these types, this only happens when
47    /// later proving the `Subtype(?0, ?1)` goal from the first relation.
48    cache: DelayedSet<(ty::Variance, Ty<'tcx>, Ty<'tcx>)>,
49}
50
51impl<'infcx, 'tcx> TypeRelating<'infcx, 'tcx> {
52    pub(crate) fn new(
53        infcx: &'infcx InferCtxt<'tcx>,
54        trace: TypeTrace<'tcx>,
55        param_env: ty::ParamEnv<'tcx>,
56        define_opaque_types: DefineOpaqueTypes,
57        ambient_variance: ty::Variance,
58    ) -> TypeRelating<'infcx, 'tcx> {
59        if !!infcx.next_trait_solver {
    ::core::panicking::panic("assertion failed: !infcx.next_trait_solver")
};assert!(!infcx.next_trait_solver);
60        TypeRelating {
61            infcx,
62            trace,
63            param_env,
64            define_opaque_types,
65            ambient_variance,
66            obligations: PredicateObligations::new(),
67            cache: Default::default(),
68        }
69    }
70
71    pub(crate) fn into_obligations(self) -> PredicateObligations<'tcx> {
72        self.obligations
73    }
74}
75
76impl<'tcx> TypeRelation<TyCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
77    fn cx(&self) -> TyCtxt<'tcx> {
78        self.infcx.tcx
79    }
80
81    fn relate_ty_args(
82        &mut self,
83        a_ty: Ty<'tcx>,
84        b_ty: Ty<'tcx>,
85        def_id: DefId,
86        a_args: ty::GenericArgsRef<'tcx>,
87        b_args: ty::GenericArgsRef<'tcx>,
88        _: impl FnOnce(ty::GenericArgsRef<'tcx>) -> Ty<'tcx>,
89    ) -> RelateResult<'tcx, Ty<'tcx>> {
90        if self.ambient_variance == ty::Invariant {
91            // Avoid fetching the variance if we are in an invariant
92            // context; no need, and it can induce dependency cycles
93            // (e.g., #41849).
94            relate_args_invariantly(self, a_args, b_args)?;
95            Ok(a_ty)
96        } else {
97            let variances = self.cx().variances_of(def_id);
98            combine_ty_args(self.infcx, self, a_ty, b_ty, variances, a_args, b_args, |_| a_ty)
99        }
100    }
101
102    fn relate_with_variance<T: Relate<TyCtxt<'tcx>>>(
103        &mut self,
104        variance: ty::Variance,
105        _info: ty::VarianceDiagInfo<TyCtxt<'tcx>>,
106        a: T,
107        b: T,
108    ) -> RelateResult<'tcx, T> {
109        let old_ambient_variance = self.ambient_variance;
110        self.ambient_variance = self.ambient_variance.xform(variance);
111        {
    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/type_relating.rs:111",
                        "rustc_infer::infer::relate::type_relating",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/type_relating.rs"),
                        ::tracing_core::__macro_support::Option::Some(111u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::type_relating"),
                        ::tracing_core::field::FieldSet::new(&["message",
                                        "self.ambient_variance"],
                            ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("new ambient variance")
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&self.ambient_variance)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(?self.ambient_variance, "new ambient variance");
112
113        let r = if self.ambient_variance == ty::Bivariant { Ok(a) } else { self.relate(a, b) };
114
115        self.ambient_variance = old_ambient_variance;
116        r
117    }
118
119    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("tys",
                                    "rustc_infer::infer::relate::type_relating",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/type_relating.rs"),
                                    ::tracing_core::__macro_support::Option::Some(119u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::type_relating"),
                                    ::tracing_core::field::FieldSet::new(&["a", "b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
                                                            as &dyn 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, Ty<'tcx>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            if true {
                if !!a.has_rigid_aliases() {
                    ::core::panicking::panic("assertion failed: !a.has_rigid_aliases()")
                };
            };
            if true {
                if !!b.has_rigid_aliases() {
                    ::core::panicking::panic("assertion failed: !b.has_rigid_aliases()")
                };
            };
            if a == b { return Ok(a); }
            let infcx = self.infcx;
            let a = infcx.shallow_resolve(a);
            let b = infcx.shallow_resolve(b);
            if self.cache.contains(&(self.ambient_variance, a, b)) {
                return Ok(a);
            }
            match (a.kind(), b.kind()) {
                (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
                    match self.ambient_variance {
                        ty::Covariant => {
                            self.obligations.push(Obligation::new(self.cx(),
                                    self.trace.cause.clone(), self.param_env,
                                    ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                                a_is_expected: true,
                                                a,
                                                b,
                                            }))));
                        }
                        ty::Contravariant => {
                            self.obligations.push(Obligation::new(self.cx(),
                                    self.trace.cause.clone(), self.param_env,
                                    ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
                                                a_is_expected: false,
                                                a: b,
                                                b: a,
                                            }))));
                        }
                        ty::Invariant => {
                            infcx.inner.borrow_mut().type_variables().equate(a_id,
                                b_id);
                        }
                        ty::Bivariant => {
                            {
                                ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
                                        format_args!("Expected bivariance to be handled in relate_with_variance")));
                            }
                        }
                    }
                }
                (&ty::Infer(TyVar(a_vid)), _) => {
                    infcx.instantiate_ty_var(self, true, a_vid,
                            self.ambient_variance, b)?;
                }
                (_, &ty::Infer(TyVar(b_vid))) => {
                    infcx.instantiate_ty_var(self, false, b_vid,
                            self.ambient_variance.xform(ty::Contravariant), a)?;
                }
                (&ty::Alias(_, ty::AliasTy {
                    kind: ty::Opaque { def_id: a_def_id }, .. }),
                    &ty::Alias(_, ty::AliasTy {
                    kind: ty::Opaque { def_id: b_def_id }, .. })) if
                    a_def_id == b_def_id => {
                    super_combine_tys(infcx, self, a, b)?;
                }
                (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
                    }), _) |
                    (_,
                    &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, ..
                    })) if
                    self.define_opaque_types == DefineOpaqueTypes::Yes &&
                        def_id.is_local() => {
                    self.register_goals(infcx.handle_opaque_type(a, b,
                                self.trace.cause.span, self.param_env())?);
                }
                _ => { super_combine_tys(infcx, self, a, b)?; }
            }
            if !self.cache.insert((self.ambient_variance, a, b)) {
                ::core::panicking::panic("assertion failed: self.cache.insert((self.ambient_variance, a, b))")
            };
            Ok(a)
        }
    }
}#[instrument(skip(self), level = "trace")]
120    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
121        // We don't use the rigid marker in the old solver.
122        debug_assert!(!a.has_rigid_aliases());
123        debug_assert!(!b.has_rigid_aliases());
124
125        if a == b {
126            return Ok(a);
127        }
128
129        let infcx = self.infcx;
130        let a = infcx.shallow_resolve(a);
131        let b = infcx.shallow_resolve(b);
132
133        if self.cache.contains(&(self.ambient_variance, a, b)) {
134            return Ok(a);
135        }
136
137        match (a.kind(), b.kind()) {
138            (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
139                match self.ambient_variance {
140                    ty::Covariant => {
141                        // can't make progress on `A <: B` if both A and B are
142                        // type variables, so record an obligation.
143                        self.obligations.push(Obligation::new(
144                            self.cx(),
145                            self.trace.cause.clone(),
146                            self.param_env,
147                            ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
148                                a_is_expected: true,
149                                a,
150                                b,
151                            })),
152                        ));
153                    }
154                    ty::Contravariant => {
155                        // can't make progress on `B <: A` if both A and B are
156                        // type variables, so record an obligation.
157                        self.obligations.push(Obligation::new(
158                            self.cx(),
159                            self.trace.cause.clone(),
160                            self.param_env,
161                            ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
162                                a_is_expected: false,
163                                a: b,
164                                b: a,
165                            })),
166                        ));
167                    }
168                    ty::Invariant => {
169                        infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
170                    }
171                    ty::Bivariant => {
172                        unreachable!("Expected bivariance to be handled in relate_with_variance")
173                    }
174                }
175            }
176
177            (&ty::Infer(TyVar(a_vid)), _) => {
178                infcx.instantiate_ty_var(self, true, a_vid, self.ambient_variance, b)?;
179            }
180            (_, &ty::Infer(TyVar(b_vid))) => {
181                infcx.instantiate_ty_var(
182                    self,
183                    false,
184                    b_vid,
185                    self.ambient_variance.xform(ty::Contravariant),
186                    a,
187                )?;
188            }
189
190            (
191                &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }),
192                &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }),
193            ) if a_def_id == b_def_id => {
194                super_combine_tys(infcx, self, a, b)?;
195            }
196
197            (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _)
198            | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }))
199                if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() =>
200            {
201                self.register_goals(infcx.handle_opaque_type(
202                    a,
203                    b,
204                    self.trace.cause.span,
205                    self.param_env(),
206                )?);
207            }
208
209            _ => {
210                super_combine_tys(infcx, self, a, b)?;
211            }
212        }
213
214        assert!(self.cache.insert((self.ambient_variance, a, b)));
215
216        Ok(a)
217    }
218
219    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("regions",
                                    "rustc_infer::infer::relate::type_relating",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/type_relating.rs"),
                                    ::tracing_core::__macro_support::Option::Some(219u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::type_relating"),
                                    ::tracing_core::field::FieldSet::new(&["a", "b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
                                                            as &dyn 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, ty::Region<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let origin =
                SubregionOrigin::Subtype(Box::new(self.trace.clone()));
            match self.ambient_variance {
                ty::Covariant => {
                    self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin,
                        b, a, ty::VisibleForLeakCheck::Yes);
                }
                ty::Contravariant => {
                    self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin,
                        a, b, ty::VisibleForLeakCheck::Yes);
                }
                ty::Invariant => {
                    self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin,
                        a, b, ty::VisibleForLeakCheck::Yes);
                }
                ty::Bivariant => {
                    {
                        ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
                                format_args!("Expected bivariance to be handled in relate_with_variance")));
                    }
                }
            }
            Ok(a)
        }
    }
}#[instrument(skip(self), level = "trace")]
220    fn regions(
221        &mut self,
222        a: ty::Region<'tcx>,
223        b: ty::Region<'tcx>,
224    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
225        let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
226
227        match self.ambient_variance {
228            // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
229            ty::Covariant => {
230                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
231                    origin,
232                    b,
233                    a,
234                    ty::VisibleForLeakCheck::Yes,
235                );
236            }
237            // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
238            ty::Contravariant => {
239                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
240                    origin,
241                    a,
242                    b,
243                    ty::VisibleForLeakCheck::Yes,
244                );
245            }
246            ty::Invariant => {
247                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
248                    origin,
249                    a,
250                    b,
251                    ty::VisibleForLeakCheck::Yes,
252                );
253            }
254            ty::Bivariant => {
255                unreachable!("Expected bivariance to be handled in relate_with_variance")
256            }
257        }
258
259        Ok(a)
260    }
261
262    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("consts",
                                    "rustc_infer::infer::relate::type_relating",
                                    ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/relate/type_relating.rs"),
                                    ::tracing_core::__macro_support::Option::Some(262u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_infer::infer::relate::type_relating"),
                                    ::tracing_core::field::FieldSet::new(&["a", "b"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&a)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&b)
                                                            as &dyn 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, ty::Const<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if true {
                if !!a.has_rigid_aliases() {
                    ::core::panicking::panic("assertion failed: !a.has_rigid_aliases()")
                };
            };
            if true {
                if !!b.has_rigid_aliases() {
                    ::core::panicking::panic("assertion failed: !b.has_rigid_aliases()")
                };
            };
            super_combine_consts(self.infcx, self, a, b)
        }
    }
}#[instrument(skip(self), level = "trace")]
263    fn consts(
264        &mut self,
265        a: ty::Const<'tcx>,
266        b: ty::Const<'tcx>,
267    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
268        // We don't use the rigid marker in the old solver.
269        debug_assert!(!a.has_rigid_aliases());
270        debug_assert!(!b.has_rigid_aliases());
271
272        super_combine_consts(self.infcx, self, a, b)
273    }
274
275    fn binders<T>(
276        &mut self,
277        a: ty::Binder<'tcx, T>,
278        b: ty::Binder<'tcx, T>,
279    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
280    where
281        T: Relate<TyCtxt<'tcx>>,
282    {
283        if a == b {
284            // Do nothing
285        } else if let Some(a) = a.no_bound_vars()
286            && let Some(b) = b.no_bound_vars()
287        {
288            self.relate(a, b)?;
289        } else {
290            let span = self.trace.cause.span;
291            let infcx = self.infcx;
292
293            match self.ambient_variance {
294                // Checks whether `for<..> sub <: for<..> sup` holds.
295                //
296                // For this to hold, **all** instantiations of the super type
297                // have to be a super type of **at least one** instantiation of
298                // the subtype.
299                //
300                // This is implemented by first entering a new universe.
301                // We then replace all bound variables in `sup` with placeholders,
302                // and all bound variables in `sub` with inference vars.
303                // We can then just relate the two resulting types as normal.
304                //
305                // Note: this is a subtle algorithm. For a full explanation, please see
306                // the [rustc dev guide][rd]
307                //
308                // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
309                ty::Covariant => {
310                    infcx.enter_forall(b, |b| {
311                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
312                        self.relate(a, b)
313                    })?;
314                }
315                ty::Contravariant => {
316                    infcx.enter_forall(a, |a| {
317                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
318                        self.relate(a, b)
319                    })?;
320                }
321
322                // When **equating** binders, we check that there is a 1-to-1
323                // correspondence between the bound vars in both types.
324                //
325                // We do so by separately instantiating one of the binders with
326                // placeholders and the other with inference variables and then
327                // equating the instantiated types.
328                //
329                // We want `for<..> A == for<..> B` -- therefore we want
330                // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
331                // Check if `exists<..> A == for<..> B`
332                ty::Invariant => {
333                    infcx.enter_forall(b, |b| {
334                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
335                        self.relate(a, b)
336                    })?;
337
338                    // Check if `exists<..> B == for<..> A`.
339                    infcx.enter_forall(a, |a| {
340                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
341                        self.relate(a, b)
342                    })?;
343                }
344                ty::Bivariant => {
345                    {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("Expected bivariance to be handled in relate_with_variance")));
}unreachable!("Expected bivariance to be handled in relate_with_variance")
346                }
347            }
348        }
349
350        Ok(a)
351    }
352}
353
354impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
355    fn span(&self) -> Span {
356        self.trace.span()
357    }
358
359    fn param_env(&self) -> ty::ParamEnv<'tcx> {
360        self.param_env
361    }
362
363    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
364        StructurallyRelateAliases::No
365    }
366
367    fn register_predicates(
368        &mut self,
369        preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
370    ) {
371        self.obligations.extend(preds.into_iter().map(|pred| {
372            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
373        }))
374    }
375
376    fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
377        self.obligations.extend(goals.into_iter().map(|goal| {
378            Obligation::new(
379                self.infcx.tcx,
380                self.trace.cause.clone(),
381                goal.param_env,
382                goal.predicate,
383            )
384        }))
385    }
386
387    fn ambient_variance(&self) -> ty::Variance {
388        self.ambient_variance
389    }
390}