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};
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 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        if a == b {
122            return Ok(a);
123        }
124
125        let infcx = self.infcx;
126        let a = infcx.shallow_resolve(a);
127        let b = infcx.shallow_resolve(b);
128
129        if self.cache.contains(&(self.ambient_variance, a, b)) {
130            return Ok(a);
131        }
132
133        match (a.kind(), b.kind()) {
134            (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => {
135                match self.ambient_variance {
136                    ty::Covariant => {
137                        // can't make progress on `A <: B` if both A and B are
138                        // type variables, so record an obligation.
139                        self.obligations.push(Obligation::new(
140                            self.cx(),
141                            self.trace.cause.clone(),
142                            self.param_env,
143                            ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
144                                a_is_expected: true,
145                                a,
146                                b,
147                            })),
148                        ));
149                    }
150                    ty::Contravariant => {
151                        // can't make progress on `B <: A` if both A and B are
152                        // type variables, so record an obligation.
153                        self.obligations.push(Obligation::new(
154                            self.cx(),
155                            self.trace.cause.clone(),
156                            self.param_env,
157                            ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate {
158                                a_is_expected: false,
159                                a: b,
160                                b: a,
161                            })),
162                        ));
163                    }
164                    ty::Invariant => {
165                        infcx.inner.borrow_mut().type_variables().equate(a_id, b_id);
166                    }
167                    ty::Bivariant => {
168                        unreachable!("Expected bivariance to be handled in relate_with_variance")
169                    }
170                }
171            }
172
173            (&ty::Infer(TyVar(a_vid)), _) => {
174                infcx.instantiate_ty_var(self, true, a_vid, self.ambient_variance, b)?;
175            }
176            (_, &ty::Infer(TyVar(b_vid))) => {
177                infcx.instantiate_ty_var(
178                    self,
179                    false,
180                    b_vid,
181                    self.ambient_variance.xform(ty::Contravariant),
182                    a,
183                )?;
184            }
185
186            (
187                &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }),
188                &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }),
189            ) if a_def_id == b_def_id => {
190                super_combine_tys(infcx, self, a, b)?;
191            }
192
193            (&ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _)
194            | (_, &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }))
195                if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() =>
196            {
197                self.register_goals(infcx.handle_opaque_type(
198                    a,
199                    b,
200                    self.trace.cause.span,
201                    self.param_env(),
202                )?);
203            }
204
205            _ => {
206                super_combine_tys(infcx, self, a, b)?;
207            }
208        }
209
210        assert!(self.cache.insert((self.ambient_variance, a, b)));
211
212        Ok(a)
213    }
214
215    #[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(215u32),
                                    ::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")]
216    fn regions(
217        &mut self,
218        a: ty::Region<'tcx>,
219        b: ty::Region<'tcx>,
220    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
221        let origin = SubregionOrigin::Subtype(Box::new(self.trace.clone()));
222
223        match self.ambient_variance {
224            // Subtype(&'a u8, &'b u8) => Outlives('a: 'b) => SubRegion('b, 'a)
225            ty::Covariant => {
226                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
227                    origin,
228                    b,
229                    a,
230                    ty::VisibleForLeakCheck::Yes,
231                );
232            }
233            // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
234            ty::Contravariant => {
235                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(
236                    origin,
237                    a,
238                    b,
239                    ty::VisibleForLeakCheck::Yes,
240                );
241            }
242            ty::Invariant => {
243                self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion(
244                    origin,
245                    a,
246                    b,
247                    ty::VisibleForLeakCheck::Yes,
248                );
249            }
250            ty::Bivariant => {
251                unreachable!("Expected bivariance to be handled in relate_with_variance")
252            }
253        }
254
255        Ok(a)
256    }
257
258    #[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(258u32),
                                    ::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;
        }
        { super_combine_consts(self.infcx, self, a, b) }
    }
}#[instrument(skip(self), level = "trace")]
259    fn consts(
260        &mut self,
261        a: ty::Const<'tcx>,
262        b: ty::Const<'tcx>,
263    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
264        super_combine_consts(self.infcx, self, a, b)
265    }
266
267    fn binders<T>(
268        &mut self,
269        a: ty::Binder<'tcx, T>,
270        b: ty::Binder<'tcx, T>,
271    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
272    where
273        T: Relate<TyCtxt<'tcx>>,
274    {
275        if a == b {
276            // Do nothing
277        } else if let Some(a) = a.no_bound_vars()
278            && let Some(b) = b.no_bound_vars()
279        {
280            self.relate(a, b)?;
281        } else {
282            let span = self.trace.cause.span;
283            let infcx = self.infcx;
284
285            match self.ambient_variance {
286                // Checks whether `for<..> sub <: for<..> sup` holds.
287                //
288                // For this to hold, **all** instantiations of the super type
289                // have to be a super type of **at least one** instantiation of
290                // the subtype.
291                //
292                // This is implemented by first entering a new universe.
293                // We then replace all bound variables in `sup` with placeholders,
294                // and all bound variables in `sub` with inference vars.
295                // We can then just relate the two resulting types as normal.
296                //
297                // Note: this is a subtle algorithm. For a full explanation, please see
298                // the [rustc dev guide][rd]
299                //
300                // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
301                ty::Covariant => {
302                    infcx.enter_forall(b, |b| {
303                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
304                        self.relate(a, b)
305                    })?;
306                }
307                ty::Contravariant => {
308                    infcx.enter_forall(a, |a| {
309                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
310                        self.relate(a, b)
311                    })?;
312                }
313
314                // When **equating** binders, we check that there is a 1-to-1
315                // correspondence between the bound vars in both types.
316                //
317                // We do so by separately instantiating one of the binders with
318                // placeholders and the other with inference variables and then
319                // equating the instantiated types.
320                //
321                // We want `for<..> A == for<..> B` -- therefore we want
322                // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
323                // Check if `exists<..> A == for<..> B`
324                ty::Invariant => {
325                    infcx.enter_forall(b, |b| {
326                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
327                        self.relate(a, b)
328                    })?;
329
330                    // Check if `exists<..> B == for<..> A`.
331                    infcx.enter_forall(a, |a| {
332                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
333                        self.relate(a, b)
334                    })?;
335                }
336                ty::Bivariant => {
337                    {
    ::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")
338                }
339            }
340        }
341
342        Ok(a)
343    }
344}
345
346impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
347    fn span(&self) -> Span {
348        self.trace.span()
349    }
350
351    fn param_env(&self) -> ty::ParamEnv<'tcx> {
352        self.param_env
353    }
354
355    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
356        StructurallyRelateAliases::No
357    }
358
359    fn register_predicates(
360        &mut self,
361        preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
362    ) {
363        self.obligations.extend(preds.into_iter().map(|pred| {
364            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
365        }))
366    }
367
368    fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
369        self.obligations.extend(goals.into_iter().map(|goal| {
370            Obligation::new(
371                self.infcx.tcx,
372                self.trace.cause.clone(),
373                goal.param_env,
374                goal.predicate,
375            )
376        }))
377    }
378
379    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
380        self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
381            ty::Covariant => ty::PredicateKind::AliasRelate(
382                a.into(),
383                b.into(),
384                ty::AliasRelationDirection::Subtype,
385            ),
386            // a :> b is b <: a
387            ty::Contravariant => ty::PredicateKind::AliasRelate(
388                b.into(),
389                a.into(),
390                ty::AliasRelationDirection::Subtype,
391            ),
392            ty::Invariant => ty::PredicateKind::AliasRelate(
393                a.into(),
394                b.into(),
395                ty::AliasRelationDirection::Equate,
396            ),
397            ty::Bivariant => {
398                {
    ::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")
399            }
400        })]);
401    }
402}