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::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
                    &ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, ..
                    })) if a_def_id == b_def_id => {
                    super_combine_tys(infcx, self, a, b)?;
                }
                (&ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }), _) |
                    (_, &ty::Alias(ty::Opaque, ty::AliasTy { 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::Opaque, ty::AliasTy { def_id: a_def_id, .. }),
188                &ty::Alias(ty::Opaque, ty::AliasTy { 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::Opaque, ty::AliasTy { def_id, .. }), _)
194            | (_, &ty::Alias(ty::Opaque, ty::AliasTy { 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::Contravariant => {
                    self.infcx.inner.borrow_mut().unwrap_region_constraints().make_subregion(origin,
                        a, b);
                }
                ty::Invariant => {
                    self.infcx.inner.borrow_mut().unwrap_region_constraints().make_eqregion(origin,
                        a, b);
                }
                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
227                    .inner
228                    .borrow_mut()
229                    .unwrap_region_constraints()
230                    .make_subregion(origin, b, a);
231            }
232            // Suptype(&'a u8, &'b u8) => Outlives('b: 'a) => SubRegion('a, 'b)
233            ty::Contravariant => {
234                self.infcx
235                    .inner
236                    .borrow_mut()
237                    .unwrap_region_constraints()
238                    .make_subregion(origin, a, b);
239            }
240            ty::Invariant => {
241                self.infcx
242                    .inner
243                    .borrow_mut()
244                    .unwrap_region_constraints()
245                    .make_eqregion(origin, a, b);
246            }
247            ty::Bivariant => {
248                unreachable!("Expected bivariance to be handled in relate_with_variance")
249            }
250        }
251
252        Ok(a)
253    }
254
255    #[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(255u32),
                                    ::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")]
256    fn consts(
257        &mut self,
258        a: ty::Const<'tcx>,
259        b: ty::Const<'tcx>,
260    ) -> RelateResult<'tcx, ty::Const<'tcx>> {
261        super_combine_consts(self.infcx, self, a, b)
262    }
263
264    fn binders<T>(
265        &mut self,
266        a: ty::Binder<'tcx, T>,
267        b: ty::Binder<'tcx, T>,
268    ) -> RelateResult<'tcx, ty::Binder<'tcx, T>>
269    where
270        T: Relate<TyCtxt<'tcx>>,
271    {
272        if a == b {
273            // Do nothing
274        } else if let Some(a) = a.no_bound_vars()
275            && let Some(b) = b.no_bound_vars()
276        {
277            self.relate(a, b)?;
278        } else {
279            let span = self.trace.cause.span;
280            let infcx = self.infcx;
281
282            match self.ambient_variance {
283                // Checks whether `for<..> sub <: for<..> sup` holds.
284                //
285                // For this to hold, **all** instantiations of the super type
286                // have to be a super type of **at least one** instantiation of
287                // the subtype.
288                //
289                // This is implemented by first entering a new universe.
290                // We then replace all bound variables in `sup` with placeholders,
291                // and all bound variables in `sub` with inference vars.
292                // We can then just relate the two resulting types as normal.
293                //
294                // Note: this is a subtle algorithm. For a full explanation, please see
295                // the [rustc dev guide][rd]
296                //
297                // [rd]: https://rustc-dev-guide.rust-lang.org/borrow_check/region_inference/placeholders_and_universes.html
298                ty::Covariant => {
299                    infcx.enter_forall(b, |b| {
300                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
301                        self.relate(a, b)
302                    })?;
303                }
304                ty::Contravariant => {
305                    infcx.enter_forall(a, |a| {
306                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
307                        self.relate(a, b)
308                    })?;
309                }
310
311                // When **equating** binders, we check that there is a 1-to-1
312                // correspondence between the bound vars in both types.
313                //
314                // We do so by separately instantiating one of the binders with
315                // placeholders and the other with inference variables and then
316                // equating the instantiated types.
317                //
318                // We want `for<..> A == for<..> B` -- therefore we want
319                // `exists<..> A == for<..> B` and `exists<..> B == for<..> A`.
320                // Check if `exists<..> A == for<..> B`
321                ty::Invariant => {
322                    infcx.enter_forall(b, |b| {
323                        let a = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, a);
324                        self.relate(a, b)
325                    })?;
326
327                    // Check if `exists<..> B == for<..> A`.
328                    infcx.enter_forall(a, |a| {
329                        let b = infcx.instantiate_binder_with_fresh_vars(span, HigherRankedType, b);
330                        self.relate(a, b)
331                    })?;
332                }
333                ty::Bivariant => {
334                    {
    ::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")
335                }
336            }
337        }
338
339        Ok(a)
340    }
341}
342
343impl<'tcx> PredicateEmittingRelation<InferCtxt<'tcx>> for TypeRelating<'_, 'tcx> {
344    fn span(&self) -> Span {
345        self.trace.span()
346    }
347
348    fn param_env(&self) -> ty::ParamEnv<'tcx> {
349        self.param_env
350    }
351
352    fn structurally_relate_aliases(&self) -> StructurallyRelateAliases {
353        StructurallyRelateAliases::No
354    }
355
356    fn register_predicates(
357        &mut self,
358        preds: impl IntoIterator<Item: ty::Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>>,
359    ) {
360        self.obligations.extend(preds.into_iter().map(|pred| {
361            Obligation::new(self.infcx.tcx, self.trace.cause.clone(), self.param_env, pred)
362        }))
363    }
364
365    fn register_goals(&mut self, goals: impl IntoIterator<Item = Goal<'tcx, ty::Predicate<'tcx>>>) {
366        self.obligations.extend(goals.into_iter().map(|goal| {
367            Obligation::new(
368                self.infcx.tcx,
369                self.trace.cause.clone(),
370                goal.param_env,
371                goal.predicate,
372            )
373        }))
374    }
375
376    fn register_alias_relate_predicate(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) {
377        self.register_predicates([ty::Binder::dummy(match self.ambient_variance {
378            ty::Covariant => ty::PredicateKind::AliasRelate(
379                a.into(),
380                b.into(),
381                ty::AliasRelationDirection::Subtype,
382            ),
383            // a :> b is b <: a
384            ty::Contravariant => ty::PredicateKind::AliasRelate(
385                b.into(),
386                a.into(),
387                ty::AliasRelationDirection::Subtype,
388            ),
389            ty::Invariant => ty::PredicateKind::AliasRelate(
390                a.into(),
391                b.into(),
392                ty::AliasRelationDirection::Equate,
393            ),
394            ty::Bivariant => {
395                {
    ::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")
396            }
397        })]);
398    }
399}