Skip to main content

rustc_ty_utils/
abi.rs

1use std::{assert_matches, iter};
2
3use rustc_abi::Primitive::Pointer;
4use rustc_abi::{Align, BackendRepr, ExternAbi, PointerKind, Scalar, Size};
5use rustc_attr_ir::find_attr;
6use rustc_attr_ir::lang_items::LangItem;
7use rustc_hir as hir;
8use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs;
9use rustc_middle::query::Providers;
10use rustc_middle::ty::layout::{
11    FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind,
12};
13use rustc_middle::ty::{self, Instance, InstanceKind, ShimKind, Ty, TyCtxt, Unnormalized};
14use rustc_span::def_id::DefId;
15use rustc_span::{DUMMY_SP, bug};
16use rustc_target::callconv::{
17    AbiMap, ArgAbi, ArgAttribute, ArgAttributes, FnAbi, IndirectMode, PassMode,
18};
19use tracing::debug;
20
21pub(crate) fn provide(providers: &mut Providers) {
22    *providers = Providers {
23        fn_abi_of_fn_ptr,
24        fn_abi_of_instance_no_deduced_attrs,
25        fn_abi_of_instance_raw,
26        ..*providers
27    };
28}
29
30// NOTE(eddyb) this is private to avoid using it from outside of
31// `fn_abi_of_instance` - any other uses are either too high-level
32// for `Instance` (e.g. typeck would use `Ty::fn_sig` instead),
33// or should go through `FnAbi` instead, to avoid losing any
34// adjustments `fn_abi_of_instance` might be performing.
35{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("fn_sig_for_fn_abi",
                                    "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(35u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("instance")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("instance");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instance)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: ty::FnSig<'tcx> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if let InstanceKind::Shim(ShimKind::ThreadLocal(..)) =
                    instance.def {
                return tcx.mk_fn_sig_safe_rust_abi([],
                        tcx.thread_local_ptr_ty(instance.def_id()));
            }
            let ty = instance.ty(tcx, typing_env);
            match *ty.kind() {
                ty::FnDef(def_id, args) => {
                    let mut sig =
                        tcx.instantiate_bound_regions_with_erased(tcx.fn_sig(def_id).instantiate(tcx,
                                    args.no_bound_vars().unwrap()).skip_norm_wip());
                    if let ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) =
                            instance.def {
                        let mut inputs_and_output = sig.inputs_and_output.to_vec();
                        inputs_and_output[0] =
                            Ty::new_mut_ptr(tcx, inputs_and_output[0]);
                        sig.inputs_and_output =
                            tcx.mk_type_list(&inputs_and_output);
                    }
                    sig
                }
                ty::Closure(def_id, args) => {
                    let sig =
                        tcx.instantiate_bound_regions_with_erased(args.as_closure().sig());
                    let env_ty =
                        tcx.closure_env_ty(Ty::new_closure(tcx, def_id, args),
                            args.as_closure().kind(), tcx.lifetimes.re_erased);
                    tcx.mk_fn_sig(iter::once(env_ty).chain(sig.inputs().iter().cloned()),
                        sig.output(), sig.fn_sig_kind)
                }
                ty::CoroutineClosure(def_id, args) => {
                    let coroutine_ty =
                        Ty::new_coroutine_closure(tcx, def_id, args);
                    let sig =
                        args.as_coroutine_closure().coroutine_closure_sig();
                    let mut coroutine_kind = args.as_coroutine_closure().kind();
                    let env_ty =
                        if let InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure {
                                receiver_by_ref, .. }) = instance.def {
                            coroutine_kind = ty::ClosureKind::FnOnce;
                            if receiver_by_ref {
                                Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
                            } else { coroutine_ty }
                        } else {
                            tcx.closure_env_ty(coroutine_ty, coroutine_kind,
                                tcx.lifetimes.re_erased)
                        };
                    let sig = tcx.instantiate_bound_regions_with_erased(sig);
                    tcx.mk_fn_sig(iter::once(env_ty).chain([sig.tupled_inputs_ty]),
                        sig.to_coroutine_given_kind_and_upvars(tcx,
                            args.as_coroutine_closure().parent_args(),
                            tcx.coroutine_for_closure(def_id), coroutine_kind,
                            tcx.lifetimes.re_erased,
                            args.as_coroutine_closure().tupled_upvars_ty(),
                            args.as_coroutine_closure().coroutine_captures_by_ref_ty()),
                        sig.fn_sig_kind)
                }
                ty::Coroutine(did, args) => {
                    let coroutine_kind = tcx.coroutine_kind(did).unwrap();
                    let sig = args.as_coroutine().sig();
                    let env_ty =
                        Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
                    let pin_did =
                        tcx.require_lang_item(LangItem::Pin, DUMMY_SP);
                    let pin_adt_ref = tcx.adt_def(pin_did);
                    let pin_args = tcx.mk_args(&[env_ty.into()]);
                    let env_ty =
                        match coroutine_kind {
                            hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen,
                                _) => {
                                env_ty
                            }
                            hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
                                _) |
                                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen,
                                _) | hir::CoroutineKind::Coroutine(_) =>
                                Ty::new_adt(tcx, pin_adt_ref, pin_args),
                        };
                    let (resume_ty, ret_ty) =
                        match coroutine_kind {
                            hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async,
                                _) => {
                                {
                                    match (&sig.yield_ty, &tcx.types.unit) {
                                        (left_val, right_val) => {
                                            if !(*left_val == *right_val) {
                                                let kind = ::core::panicking::AssertKind::Eq;
                                                ::core::panicking::assert_failed(kind, &*left_val,
                                                    &*right_val, ::core::option::Option::None);
                                            }
                                        }
                                    }
                                };
                                let poll_did =
                                    tcx.require_lang_item(LangItem::Poll, DUMMY_SP);
                                let poll_adt_ref = tcx.adt_def(poll_did);
                                let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
                                let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
                                {
                                    if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
                                        let expected_adt =
                                            tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy,
                                                    DUMMY_SP));
                                        {
                                            match (&*resume_ty_adt, &expected_adt) {
                                                (left_val, right_val) => {
                                                    if !(*left_val == *right_val) {
                                                        let kind = ::core::panicking::AssertKind::Eq;
                                                        ::core::panicking::assert_failed(kind, &*left_val,
                                                            &*right_val, ::core::option::Option::None);
                                                    }
                                                }
                                            }
                                        };
                                    } else {
                                        {
                                            ::core::panicking::panic_fmt(format_args!("expected `ResumeTy`, found `{0:?}`",
                                                    sig.resume_ty));
                                        };
                                    };
                                }
                                let context_mut_ref = Ty::new_task_context(tcx);
                                (Some(context_mut_ref), ret_ty)
                            }
                            hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen,
                                _) => {
                                let option_did =
                                    tcx.require_lang_item(LangItem::Option, DUMMY_SP);
                                let option_adt_ref = tcx.adt_def(option_did);
                                let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
                                let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
                                {
                                    match (&sig.return_ty, &tcx.types.unit) {
                                        (left_val, right_val) => {
                                            if !(*left_val == *right_val) {
                                                let kind = ::core::panicking::AssertKind::Eq;
                                                ::core::panicking::assert_failed(kind, &*left_val,
                                                    &*right_val, ::core::option::Option::None);
                                            }
                                        }
                                    }
                                };
                                {
                                    match (&sig.resume_ty, &tcx.types.unit) {
                                        (left_val, right_val) => {
                                            if !(*left_val == *right_val) {
                                                let kind = ::core::panicking::AssertKind::Eq;
                                                ::core::panicking::assert_failed(kind, &*left_val,
                                                    &*right_val, ::core::option::Option::None);
                                            }
                                        }
                                    }
                                };
                                (None, ret_ty)
                            }
                            hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen,
                                _) => {
                                {
                                    match (&sig.return_ty, &tcx.types.unit) {
                                        (left_val, right_val) => {
                                            if !(*left_val == *right_val) {
                                                let kind = ::core::panicking::AssertKind::Eq;
                                                ::core::panicking::assert_failed(kind, &*left_val,
                                                    &*right_val, ::core::option::Option::None);
                                            }
                                        }
                                    }
                                };
                                let ret_ty = sig.yield_ty;
                                {
                                    if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
                                        let expected_adt =
                                            tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy,
                                                    DUMMY_SP));
                                        {
                                            match (&*resume_ty_adt, &expected_adt) {
                                                (left_val, right_val) => {
                                                    if !(*left_val == *right_val) {
                                                        let kind = ::core::panicking::AssertKind::Eq;
                                                        ::core::panicking::assert_failed(kind, &*left_val,
                                                            &*right_val, ::core::option::Option::None);
                                                    }
                                                }
                                            }
                                        };
                                    } else {
                                        {
                                            ::core::panicking::panic_fmt(format_args!("expected `ResumeTy`, found `{0:?}`",
                                                    sig.resume_ty));
                                        };
                                    };
                                }
                                let context_mut_ref = Ty::new_task_context(tcx);
                                (Some(context_mut_ref), ret_ty)
                            }
                            hir::CoroutineKind::Coroutine(_) => {
                                let state_did =
                                    tcx.require_lang_item(LangItem::CoroutineState, DUMMY_SP);
                                let state_adt_ref = tcx.adt_def(state_did);
                                let state_args =
                                    tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
                                let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
                                (Some(sig.resume_ty), ret_ty)
                            }
                        };
                    if let Some(resume_ty) = resume_ty {
                        tcx.mk_fn_sig_safe_rust_abi([env_ty, resume_ty], ret_ty)
                    } else { tcx.mk_fn_sig_safe_rust_abi([env_ty], ret_ty) }
                }
                _ =>
                    ::rustc_span::macros::bug_impl(None,
                        format_args!("unexpected type {0:?} in Instance::fn_sig",
                            ty), Location::caller()),
            }
        }
    }
}#[tracing::instrument(level = "debug", skip(tcx, typing_env))]
36fn fn_sig_for_fn_abi<'tcx>(
37    tcx: TyCtxt<'tcx>,
38    instance: ty::Instance<'tcx>,
39    typing_env: ty::TypingEnv<'tcx>,
40) -> ty::FnSig<'tcx> {
41    if let InstanceKind::Shim(ShimKind::ThreadLocal(..)) = instance.def {
42        return tcx.mk_fn_sig_safe_rust_abi([], tcx.thread_local_ptr_ty(instance.def_id()));
43    }
44
45    let ty = instance.ty(tcx, typing_env);
46    match *ty.kind() {
47        ty::FnDef(def_id, args) => {
48            let mut sig = tcx.instantiate_bound_regions_with_erased(
49                tcx.fn_sig(def_id).instantiate(tcx, args.no_bound_vars().unwrap()).skip_norm_wip(),
50            );
51
52            // Modify `fn(self, ...)` to `fn(self: *mut Self, ...)`.
53            if let ty::InstanceKind::Shim(ty::ShimKind::VTable(..)) = instance.def {
54                let mut inputs_and_output = sig.inputs_and_output.to_vec();
55                inputs_and_output[0] = Ty::new_mut_ptr(tcx, inputs_and_output[0]);
56                sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
57            }
58
59            sig
60        }
61        ty::Closure(def_id, args) => {
62            let sig = tcx.instantiate_bound_regions_with_erased(args.as_closure().sig());
63            let env_ty = tcx.closure_env_ty(
64                Ty::new_closure(tcx, def_id, args),
65                args.as_closure().kind(),
66                tcx.lifetimes.re_erased,
67            );
68
69            tcx.mk_fn_sig(
70                iter::once(env_ty).chain(sig.inputs().iter().cloned()),
71                sig.output(),
72                sig.fn_sig_kind,
73            )
74        }
75        ty::CoroutineClosure(def_id, args) => {
76            let coroutine_ty = Ty::new_coroutine_closure(tcx, def_id, args);
77            let sig = args.as_coroutine_closure().coroutine_closure_sig();
78
79            // When this `CoroutineClosure` comes from a `ConstructCoroutineInClosureShim`,
80            // make sure we respect the `target_kind` in that shim.
81            // FIXME(async_closures): This shouldn't be needed, and we should be populating
82            // a separate def-id for these bodies.
83            let mut coroutine_kind = args.as_coroutine_closure().kind();
84
85            let env_ty = if let InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure {
86                receiver_by_ref,
87                ..
88            }) = instance.def
89            {
90                coroutine_kind = ty::ClosureKind::FnOnce;
91
92                // Implementations of `FnMut` and `Fn` for coroutine-closures
93                // still take their receiver by ref.
94                if receiver_by_ref {
95                    Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty)
96                } else {
97                    coroutine_ty
98                }
99            } else {
100                tcx.closure_env_ty(coroutine_ty, coroutine_kind, tcx.lifetimes.re_erased)
101            };
102
103            let sig = tcx.instantiate_bound_regions_with_erased(sig);
104
105            tcx.mk_fn_sig(
106                iter::once(env_ty).chain([sig.tupled_inputs_ty]),
107                sig.to_coroutine_given_kind_and_upvars(
108                    tcx,
109                    args.as_coroutine_closure().parent_args(),
110                    tcx.coroutine_for_closure(def_id),
111                    coroutine_kind,
112                    tcx.lifetimes.re_erased,
113                    args.as_coroutine_closure().tupled_upvars_ty(),
114                    args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
115                ),
116                sig.fn_sig_kind,
117            )
118        }
119        ty::Coroutine(did, args) => {
120            let coroutine_kind = tcx.coroutine_kind(did).unwrap();
121            let sig = args.as_coroutine().sig();
122
123            let env_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
124
125            let pin_did = tcx.require_lang_item(LangItem::Pin, DUMMY_SP);
126            let pin_adt_ref = tcx.adt_def(pin_did);
127            let pin_args = tcx.mk_args(&[env_ty.into()]);
128            let env_ty = match coroutine_kind {
129                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => {
130                    // Iterator::next doesn't accept a pinned argument,
131                    // unlike for all other coroutine kinds.
132                    env_ty
133                }
134                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
135                | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
136                | hir::CoroutineKind::Coroutine(_) => Ty::new_adt(tcx, pin_adt_ref, pin_args),
137            };
138
139            // The `FnSig` and the `ret_ty` here is for a coroutines main
140            // `Coroutine::resume(...) -> CoroutineState` function in case we
141            // have an ordinary coroutine, the `Future::poll(...) -> Poll`
142            // function in case this is a special coroutine backing an async construct
143            // or the `Iterator::next(...) -> Option` function in case this is a
144            // special coroutine backing a gen construct.
145            let (resume_ty, ret_ty) = match coroutine_kind {
146                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _) => {
147                    // The signature should be `Future::poll(_, &mut Context<'_>) -> Poll<Output>`
148                    assert_eq!(sig.yield_ty, tcx.types.unit);
149
150                    let poll_did = tcx.require_lang_item(LangItem::Poll, DUMMY_SP);
151                    let poll_adt_ref = tcx.adt_def(poll_did);
152                    let poll_args = tcx.mk_args(&[sig.return_ty.into()]);
153                    let ret_ty = Ty::new_adt(tcx, poll_adt_ref, poll_args);
154
155                    // We have to replace the `ResumeTy` that is used for type and borrow checking
156                    // with `&mut Context<'_>` which is used in codegen.
157                    #[cfg(debug_assertions)]
158                    {
159                        if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
160                            let expected_adt =
161                                tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
162                            assert_eq!(*resume_ty_adt, expected_adt);
163                        } else {
164                            panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
165                        };
166                    }
167                    let context_mut_ref = Ty::new_task_context(tcx);
168
169                    (Some(context_mut_ref), ret_ty)
170                }
171                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _) => {
172                    // The signature should be `Iterator::next(_) -> Option<Yield>`
173                    let option_did = tcx.require_lang_item(LangItem::Option, DUMMY_SP);
174                    let option_adt_ref = tcx.adt_def(option_did);
175                    let option_args = tcx.mk_args(&[sig.yield_ty.into()]);
176                    let ret_ty = Ty::new_adt(tcx, option_adt_ref, option_args);
177
178                    assert_eq!(sig.return_ty, tcx.types.unit);
179                    assert_eq!(sig.resume_ty, tcx.types.unit);
180
181                    (None, ret_ty)
182                }
183                hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _) => {
184                    // The signature should be
185                    // `AsyncIterator::poll_next(_, &mut Context<'_>) -> Poll<Option<Output>>`
186                    assert_eq!(sig.return_ty, tcx.types.unit);
187
188                    // Yield type is already `Poll<Option<yield_ty>>`
189                    let ret_ty = sig.yield_ty;
190
191                    // We have to replace the `ResumeTy` that is used for type and borrow checking
192                    // with `&mut Context<'_>` which is used in codegen.
193                    #[cfg(debug_assertions)]
194                    {
195                        if let ty::Adt(resume_ty_adt, _) = sig.resume_ty.kind() {
196                            let expected_adt =
197                                tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
198                            assert_eq!(*resume_ty_adt, expected_adt);
199                        } else {
200                            panic!("expected `ResumeTy`, found `{:?}`", sig.resume_ty);
201                        };
202                    }
203                    let context_mut_ref = Ty::new_task_context(tcx);
204
205                    (Some(context_mut_ref), ret_ty)
206                }
207                hir::CoroutineKind::Coroutine(_) => {
208                    // The signature should be `Coroutine::resume(_, Resume) -> CoroutineState<Yield, Return>`
209                    let state_did = tcx.require_lang_item(LangItem::CoroutineState, DUMMY_SP);
210                    let state_adt_ref = tcx.adt_def(state_did);
211                    let state_args = tcx.mk_args(&[sig.yield_ty.into(), sig.return_ty.into()]);
212                    let ret_ty = Ty::new_adt(tcx, state_adt_ref, state_args);
213
214                    (Some(sig.resume_ty), ret_ty)
215                }
216            };
217
218            if let Some(resume_ty) = resume_ty {
219                tcx.mk_fn_sig_safe_rust_abi([env_ty, resume_ty], ret_ty)
220            } else {
221                // `Iterator::next` doesn't have a `resume` argument.
222                tcx.mk_fn_sig_safe_rust_abi([env_ty], ret_ty)
223            }
224        }
225        _ => bug!("unexpected type {:?} in Instance::fn_sig", ty),
226    }
227}
228
229/// Describes a function for determination of its ABI.
230struct FnAbiDesc<'tcx> {
231    layout_cx: LayoutCx<'tcx>,
232    sig: ty::FnSig<'tcx>,
233
234    instance: Option<Instance<'tcx>>,
235    caller_location: Option<Ty<'tcx>>,
236    is_virtual_call: bool,
237    extra_args: &'tcx [Ty<'tcx>],
238}
239
240impl<'tcx> FnAbiDesc<'tcx> {
241    fn for_fn_ptr(
242        tcx: TyCtxt<'tcx>,
243        query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
244    ) -> Self {
245        let ty::PseudoCanonicalInput { typing_env, value: (sig, extra_args) } = query;
246        Self {
247            layout_cx: LayoutCx::new(tcx, typing_env),
248            sig: tcx.normalize_erasing_regions(
249                typing_env,
250                Unnormalized::new_wip(tcx.instantiate_bound_regions_with_erased(sig)),
251            ),
252            instance: None,
253            caller_location: None,
254            is_virtual_call: false,
255            extra_args,
256        }
257    }
258
259    fn for_instance(
260        tcx: TyCtxt<'tcx>,
261        query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
262    ) -> Self {
263        let ty::PseudoCanonicalInput { typing_env, value: (instance, extra_args) } = query;
264        let is_virtual_call = #[allow(non_exhaustive_omitted_patterns)] match instance.def {
    ty::InstanceKind::Virtual(..) => true,
    _ => false,
}matches!(instance.def, ty::InstanceKind::Virtual(..));
265        Self {
266            layout_cx: LayoutCx::new(tcx, typing_env),
267            sig: tcx.normalize_erasing_regions(
268                typing_env,
269                Unnormalized::new_wip(fn_sig_for_fn_abi(tcx, instance, typing_env)),
270            ),
271            instance: Some(instance),
272            caller_location: instance
273                .def
274                .requires_caller_location(tcx)
275                .then(|| tcx.caller_location_ty()),
276            is_virtual_call,
277            extra_args,
278        }
279    }
280}
281
282fn fn_abi_of_fn_ptr<'tcx>(
283    tcx: TyCtxt<'tcx>,
284    query: ty::PseudoCanonicalInput<'tcx, (ty::PolyFnSig<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
285) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
286    let desc = FnAbiDesc::for_fn_ptr(tcx, query);
287    fn_abi_new_uncached(desc)
288}
289
290fn fn_abi_of_instance_no_deduced_attrs<'tcx>(
291    tcx: TyCtxt<'tcx>,
292    query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
293) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
294    let desc = FnAbiDesc::for_instance(tcx, query);
295    fn_abi_new_uncached(desc)
296}
297
298fn fn_abi_of_instance_raw<'tcx>(
299    tcx: TyCtxt<'tcx>,
300    query: ty::PseudoCanonicalInput<'tcx, (ty::Instance<'tcx>, &'tcx ty::List<Ty<'tcx>>)>,
301) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
302    // The `fn_abi_of_instance_no_deduced_attrs` query may have been called during CTFE, so we
303    // delegate to it here in order to reuse (and, if necessary, augment) its result.
304    tcx.fn_abi_of_instance_no_deduced_attrs(query).map(|fn_abi| {
305        let params = FnAbiDesc::for_instance(tcx, query);
306        // Apply attributes deduced from MIR body. This requires that an instance MIR is its optimized MIR.
307        // For example, DropGlue(def_id, ty) MIR is compiler generated, while optimized MIR for def_id is
308        // that of an empty placeholder function `drop_glue` from the standard library.
309        if let Some(Instance { def: InstanceKind::Item(fn_def_id), .. }) = params.instance {
310            fn_abi_adjust_for_deduced_attrs(&params.layout_cx, fn_abi, params.sig.abi(), fn_def_id)
311        } else {
312            fn_abi
313        }
314    })
315}
316
317/// Returns argument attributes for a scalar argument.
318fn arg_attrs_for_rust_scalar<'tcx>(
319    cx: LayoutCx<'tcx>,
320    scalar: Scalar,
321    layout: TyAndLayout<'tcx>,
322    offset: Size,
323    is_return: bool,
324    instance: Option<Instance<'tcx>>,
325) -> ArgAttributes {
326    let mut attrs = ArgAttributes::new();
327
328    if !scalar.is_uninit_valid() {
329        attrs.set(ArgAttribute::NoUndef);
330    }
331
332    // Only pointer types handled below.
333    let Scalar::Initialized { value: Pointer(_), valid_range } = scalar else { return attrs };
334
335    // Set `nonnull` if the validity range excludes zero.
336    if !valid_range.contains(0) {
337        attrs.set(ArgAttribute::NonNull);
338    }
339
340    let tcx = cx.tcx();
341
342    if let Some(pointee) = layout.pointee_info_at(&cx, offset) {
343        if pointee.align > Align::ONE {
344            attrs.pointee_align =
345                Some(pointee.align.min(cx.tcx().sess.target.max_reliable_alignment()));
346        }
347
348        attrs.pointee_size = pointee.size;
349
350        if let Some(kind) = pointee.safe {
351            // The aliasing rules for `Box<T>` are still not decided, but currently we emit
352            // `noalias` for it. This can be turned off using an unstable flag.
353            // See https://github.com/rust-lang/unsafe-code-guidelines/issues/326
354            let noalias_for_box = tcx.sess.opts.unstable_opts.box_noalias;
355
356            // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
357            // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
358            // dependencies rather than pointer equality. However this only applies to arguments,
359            // not return values.
360            //
361            // `&mut T` and `Box<T>` where `T: Unpin` are unique and hence `noalias`.
362            let no_alias = match kind {
363                PointerKind::SharedRef { frozen } => frozen,
364                PointerKind::MutableRef { unpin } => unpin,
365                PointerKind::Box { unpin, global } => unpin && global && noalias_for_box,
366            };
367            // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
368            // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
369            if no_alias && !is_return {
370                attrs.set(ArgAttribute::NoAlias);
371            }
372
373            // Set writable if no_alias is set, it's a mutable reference and the feature is enabled.
374            if tcx.sess.opts.unstable_opts.llvm_writable
375                && #[allow(non_exhaustive_omitted_patterns)] match kind {
    PointerKind::MutableRef { unpin: true } => true,
    _ => false,
}matches!(kind, PointerKind::MutableRef { unpin: true })
376                && !is_return
377            {
378                if let Some(Instance { def: InstanceKind::Item(def_id), .. }) = instance {
379                    let rustc_no_writable = {
        {
            'done:
                {
                for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx) {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcNoWritable) => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(tcx, def_id, RustcNoWritable);
380                    if !rustc_no_writable {
381                        attrs.set(ArgAttribute::Writable);
382                    }
383                }
384            }
385
386            // NoFree is not valid on return values. If it were, it would mean something like
387            // "will not be freed until the end of the program", which is generally not valid for
388            // references.
389            let no_free = !is_return
390                && match kind {
391                    // Non-frozen shared references are not necessarily dereferenceable for the
392                    // entire duration of the function
393                    // (see <https://github.com/rust-lang/rust/pull/98017>).
394                    PointerKind::SharedRef { frozen } => frozen,
395                    // Mutable references to potentially self-referential types are not necessarily
396                    // dereferenceable for the entire duration of the function
397                    // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>).
398                    PointerKind::MutableRef { unpin } => unpin,
399                    // Box may be deallocated during execution of the function.
400                    PointerKind::Box { .. } => false,
401                };
402            if no_free {
403                attrs.set(ArgAttribute::NoFree);
404            }
405
406            if #[allow(non_exhaustive_omitted_patterns)] match kind {
    PointerKind::SharedRef { frozen: true } => true,
    _ => false,
}matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
407                attrs.set(ArgAttribute::ReadOnly);
408                attrs.set(ArgAttribute::CapturesReadOnly);
409            }
410        }
411    }
412
413    attrs
414}
415
416/// Ensure that the ABI makes basic sense.
417fn fn_abi_sanity_check<'tcx>(
418    cx: &LayoutCx<'tcx>,
419    fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
420    spec_abi: ExternAbi,
421) {
422    fn fn_arg_attrs_sanity_check(attrs: &ArgAttributes, is_ret: bool) {
423        if attrs.regular.contains(ArgAttribute::NoFree) {
424            if !!is_ret {
    {
        ::core::panicking::panic_fmt(format_args!("NoFree not valid on return values"));
    }
};assert!(!is_ret, "NoFree not valid on return values");
425        }
426    }
427
428    fn fn_arg_sanity_check<'tcx>(
429        cx: &LayoutCx<'tcx>,
430        spec_abi: ExternAbi,
431        arg: &ArgAbi<'tcx, Ty<'tcx>>,
432        is_ret: bool,
433    ) {
434        let tcx = cx.tcx();
435
436        if spec_abi.is_rustic_abi() {
437            if arg.layout.is_zst() {
438                // Casting closures to function pointers depends on ZST closure types being
439                // omitted entirely in the calling convention.
440                if !arg.is_ignore() {
    ::core::panicking::panic("assertion failed: arg.is_ignore()")
};assert!(arg.is_ignore());
441            }
442            if let PassMode::Indirect { mode, .. } = arg.mode
443                && spec_abi != ExternAbi::RustTail
444            {
445                if !(mode == IndirectMode::Pointer) {
    {
        ::core::panicking::panic_fmt(format_args!("rust abi must use plain pointer mode"));
    }
};assert!(mode == IndirectMode::Pointer, "rust abi must use plain pointer mode");
446            }
447        } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
448            {
    match arg.mode {
        PassMode::Indirect { mode: IndirectMode::Pointer, .. } => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "PassMode::Indirect { mode: IndirectMode::Pointer, .. }",
                ::core::option::Option::Some(format_args!("the {0} ABI does not implement `#[rustc_pass_indirectly_in_non_rustic_abis]`",
                        spec_abi)));
        }
    }
};assert_matches!(
449                arg.mode,
450                PassMode::Indirect { mode: IndirectMode::Pointer, .. },
451                "the {spec_abi} ABI does not implement `#[rustc_pass_indirectly_in_non_rustic_abis]`"
452            );
453        }
454
455        match &arg.mode {
456            PassMode::Ignore => {
457                if !arg.layout.is_zst() {
    ::core::panicking::panic("assertion failed: arg.layout.is_zst()")
};assert!(arg.layout.is_zst());
458            }
459            PassMode::Direct(attrs) => {
460                // Here the Rust type is used to determine the actual ABI, so we have to be very
461                // careful. Scalar/Vector is fine, since backends will generally use
462                // `layout.backend_repr` and ignore everything else.
463                match arg.layout.backend_repr {
464                    BackendRepr::Scalar(_)
465                    | BackendRepr::SimdVector { .. }
466                    | BackendRepr::SimdScalableVector { .. } => {}
467                    BackendRepr::ScalarPair { .. } => {
468                        {
    ::core::panicking::panic_fmt(format_args!("`PassMode::Direct` used for ScalarPair type {0}",
            arg.layout.ty));
}panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty)
469                    }
470                    BackendRepr::Memory { .. } => {
471                        {
    ::core::panicking::panic_fmt(format_args!("`PassMode::Direct` for aggregates not allowed\nProblematic type: {0:#?}",
            arg.layout));
};panic!(
472                            "`PassMode::Direct` for aggregates not allowed\n\
473                             Problematic type: {:#?}",
474                            arg.layout,
475                        );
476                    }
477                }
478                fn_arg_attrs_sanity_check(attrs, is_ret);
479            }
480            PassMode::Pair(attrs1, attrs2) => {
481                // Similar to `Direct`, we need to make sure that backends use `layout.backend_repr`
482                // and ignore the rest of the layout.
483                if !#[allow(non_exhaustive_omitted_patterns)] match arg.layout.backend_repr {
            BackendRepr::ScalarPair { .. } => true,
            _ => false,
        } {
    {
        ::core::panicking::panic_fmt(format_args!("PassMode::Pair for type {0}",
                arg.layout.ty));
    }
};assert!(
484                    matches!(arg.layout.backend_repr, BackendRepr::ScalarPair { .. }),
485                    "PassMode::Pair for type {}",
486                    arg.layout.ty
487                );
488                fn_arg_attrs_sanity_check(attrs1, is_ret);
489                fn_arg_attrs_sanity_check(attrs2, is_ret);
490            }
491            PassMode::Cast { .. } => {
492                // `Cast` means "transmute to `CastType`"; that only makes sense for sized types.
493                if !arg.layout.is_sized() {
    ::core::panicking::panic("assertion failed: arg.layout.is_sized()")
};assert!(arg.layout.is_sized());
494            }
495            PassMode::Indirect { attrs, .. } => {
496                // No metadata, must be sized.
497                // Conceptually, unsized arguments must be copied around, which requires dynamically
498                // determining their size, which we cannot do without metadata. Consult
499                // t-opsem before removing this check.
500                if !arg.layout.is_sized() {
    ::core::panicking::panic("assertion failed: arg.layout.is_sized()")
};assert!(arg.layout.is_sized());
501                // Indirect returns are arguments from an ABI perspective.
502                fn_arg_attrs_sanity_check(attrs, false);
503            }
504            PassMode::IndirectUnsized { attrs, meta_attrs } => {
505                // With metadata. Must be unsized.
506                if !arg.layout.is_unsized() {
    ::core::panicking::panic("assertion failed: arg.layout.is_unsized()")
};assert!(arg.layout.is_unsized());
507                // And must not be a return value
508                if !!is_ret { ::core::panicking::panic("assertion failed: !is_ret") };assert!(!is_ret);
509                // Also, must not be `extern` type.
510                let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env);
511                if #[allow(non_exhaustive_omitted_patterns)] match tail.kind() {
    ty::Foreign(..) => true,
    _ => false,
}matches!(tail.kind(), ty::Foreign(..)) {
512                    // These types do not have metadata, so having `meta_attrs` is bogus.
513                    // Conceptually, unsized arguments must be copied around, which requires dynamically
514                    // determining their size. Therefore, we cannot allow `extern` types here. Consult
515                    // t-opsem before removing this check.
516                    {
    ::core::panicking::panic_fmt(format_args!("unsized arguments must not be `extern` types"));
};panic!("unsized arguments must not be `extern` types");
517                }
518                // Indirect returns are arguments from an ABI perspective.
519                fn_arg_attrs_sanity_check(attrs, false);
520                fn_arg_attrs_sanity_check(meta_attrs, false);
521            }
522        }
523    }
524
525    for arg in fn_abi.args.iter() {
526        fn_arg_sanity_check(cx, spec_abi, arg, false);
527    }
528    fn_arg_sanity_check(cx, spec_abi, &fn_abi.ret, true);
529}
530
531{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("fn_abi_new_uncached",
                                    "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(531u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("sig")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("sig");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("extra_args")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("extra_args");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sig)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&extra_args)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Result<&'tcx FnAbi<'tcx, Ty<'tcx>>,
                    &'tcx FnAbiError<'tcx>> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = cx.tcx();
            let abi_map = AbiMap::from_target(&tcx.sess.target);
            let conv =
                abi_map.canonize_abi(sig.abi(), sig.c_variadic()).unwrap();
            let mut inputs = sig.inputs();
            let extra_args =
                if sig.abi() == ExternAbi::RustCall {
                    if !(!sig.c_variadic() && extra_args.is_empty()) {
                        ::core::panicking::panic("assertion failed: !sig.c_variadic() && extra_args.is_empty()")
                    };
                    if let Some(input) = sig.inputs().last() &&
                            let ty::Tuple(tupled_arguments) = input.kind() {
                        inputs = &sig.inputs()[0..sig.inputs().len() - 1];
                        tupled_arguments
                    } else {
                        ::rustc_span::macros::bug_impl(None,
                            format_args!("argument to function with \"rust-call\" ABI is not a tuple"),
                            Location::caller());
                    }
                } else {
                    if !(sig.c_variadic() || extra_args.is_empty()) {
                        ::core::panicking::panic("assertion failed: sig.c_variadic() || extra_args.is_empty()")
                    };
                    extra_args
                };
            let arg_of =
                |ty: Ty<'tcx>, arg_idx: Option<usize>|
                    -> Result<_, &'tcx FnAbiError<'tcx>>
                    {
                        let span =
                            {
                                use ::tracing::__macro_support::Callsite as _;
                                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                    {
                                        static META: ::tracing::Metadata<'static> =
                                            {
                                                ::tracing_core::metadata::Metadata::new("arg_of",
                                                    "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                                    ::tracing_core::__macro_support::Option::Some(568u32),
                                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                                    ::tracing_core::field::FieldSet::new(&[],
                                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                    ::tracing::metadata::Kind::SPAN)
                                            };
                                        ::tracing::callsite::DefaultCallsite::new(&META)
                                    };
                                let mut interest = ::tracing::subscriber::Interest::never();
                                if ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                                ::tracing::Level::DEBUG <=
                                                    ::tracing::level_filters::LevelFilter::current() &&
                                            { interest = __CALLSITE.interest(); !interest.is_never() }
                                        &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest) {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Span::new(meta,
                                        &{ meta.fields().value_set_all(&[]) })
                                } else {
                                    let span =
                                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                                    {};
                                    span
                                }
                            };
                        let _entered = span.enter();
                        let is_return = arg_idx.is_none();
                        let layout =
                            cx.layout_of(ty).map_err(|err|
                                        &*tcx.arena.alloc(FnAbiError::Layout(*err)))?;
                        let layout =
                            if is_virtual_call && arg_idx == Some(0) {
                                make_thin_self_ptr(cx, layout)
                            } else { layout };
                        Ok(ArgAbi::new(layout,
                                |scalar, offset|
                                    {
                                        arg_attrs_for_rust_scalar(*cx, scalar, layout, offset,
                                            is_return, instance)
                                    }))
                    };
            let mut fn_abi =
                FnAbi {
                    ret: arg_of(sig.output(), None)?,
                    args: inputs.iter().copied().chain(extra_args.iter().copied()).chain(caller_location).enumerate().map(|(i,
                                        ty)| arg_of(ty, Some(i))).collect::<Result<_, _>>()?,
                    c_variadic: sig.c_variadic(),
                    fixed_count: inputs.len() as u32,
                    conv,
                    can_unwind: fn_can_unwind(tcx,
                        instance.and_then(|instance|
                                match instance.def {
                                    InstanceKind::Item(item) => Some(item),
                                    InstanceKind::Intrinsic(item) => Some(item),
                                    InstanceKind::Shim(ShimKind::DropGlue(def_id, _ty)) =>
                                        Some(def_id),
                                    InstanceKind::Shim(_) => None,
                                    InstanceKind::Virtual(..) => None,
                                    InstanceKind::LlvmIntrinsic(_) => None,
                                }), sig.abi()),
                };
            fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi());
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event /rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs:618",
                                    "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(618u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&["message"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("fn_abi_new_uncached = {0:?}",
                                                                fn_abi) as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            fn_abi_sanity_check(cx, &fn_abi, sig.abi());
            Ok(tcx.arena.alloc(fn_abi))
        }
    }
}#[tracing::instrument(level = "debug", skip(cx, caller_location, instance, is_virtual_call))]
532fn fn_abi_new_uncached<'tcx>(
533    FnAbiDesc {
534        layout_cx: ref cx,
535        sig,
536        instance,
537        caller_location,
538        is_virtual_call,
539        extra_args,
540    }: FnAbiDesc<'tcx>,
541) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, &'tcx FnAbiError<'tcx>> {
542    let tcx = cx.tcx();
543
544    let abi_map = AbiMap::from_target(&tcx.sess.target);
545    let conv = abi_map.canonize_abi(sig.abi(), sig.c_variadic()).unwrap();
546
547    let mut inputs = sig.inputs();
548    let extra_args = if sig.abi() == ExternAbi::RustCall {
549        assert!(!sig.c_variadic() && extra_args.is_empty());
550
551        if let Some(input) = sig.inputs().last()
552            && let ty::Tuple(tupled_arguments) = input.kind()
553        {
554            inputs = &sig.inputs()[0..sig.inputs().len() - 1];
555            tupled_arguments
556        } else {
557            bug!(
558                "argument to function with \"rust-call\" ABI \
559                    is not a tuple"
560            );
561        }
562    } else {
563        assert!(sig.c_variadic() || extra_args.is_empty());
564        extra_args
565    };
566
567    let arg_of = |ty: Ty<'tcx>, arg_idx: Option<usize>| -> Result<_, &'tcx FnAbiError<'tcx>> {
568        let span = tracing::debug_span!("arg_of");
569        let _entered = span.enter();
570        let is_return = arg_idx.is_none();
571
572        let layout = cx.layout_of(ty).map_err(|err| &*tcx.arena.alloc(FnAbiError::Layout(*err)))?;
573        let layout = if is_virtual_call && arg_idx == Some(0) {
574            // Don't pass the vtable, it's not an argument of the virtual fn.
575            // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
576            // or `&/&mut dyn Trait` because this is special-cased elsewhere in codegen
577            make_thin_self_ptr(cx, layout)
578        } else {
579            layout
580        };
581
582        Ok(ArgAbi::new(layout, |scalar, offset| {
583            arg_attrs_for_rust_scalar(*cx, scalar, layout, offset, is_return, instance)
584        }))
585    };
586
587    let mut fn_abi = FnAbi {
588        ret: arg_of(sig.output(), None)?,
589        args: inputs
590            .iter()
591            .copied()
592            .chain(extra_args.iter().copied())
593            .chain(caller_location)
594            .enumerate()
595            .map(|(i, ty)| arg_of(ty, Some(i)))
596            .collect::<Result<_, _>>()?,
597        c_variadic: sig.c_variadic(),
598        fixed_count: inputs.len() as u32,
599        conv,
600        // FIXME return false for tls shim
601        can_unwind: fn_can_unwind(
602            tcx,
603            instance.and_then(|instance| match instance.def {
604                InstanceKind::Item(item) => Some(item),
605                InstanceKind::Intrinsic(item) => Some(item),
606                // Used to recognize that with -Z panic-in-drop=abort, `drop_glue` never unwinds.
607                InstanceKind::Shim(ShimKind::DropGlue(def_id, _ty)) => Some(def_id),
608                InstanceKind::Shim(_) => None,
609                // Don't apply rustc_nounwind from trait method to impls.
610                InstanceKind::Virtual(..) => None,
611                // Not used with fn_abi_of_instance.
612                InstanceKind::LlvmIntrinsic(_) => None,
613            }),
614            sig.abi(),
615        ),
616    };
617    fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi());
618    debug!("fn_abi_new_uncached = {:?}", fn_abi);
619    fn_abi_sanity_check(cx, &fn_abi, sig.abi());
620    Ok(tcx.arena.alloc(fn_abi))
621}
622
623{}
#[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("fn_abi_adjust_for_abi",
                                    "rustc_ty_utils::abi", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(623u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("fn_abi")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("fn_abi");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("abi")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("abi");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_abi)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&abi)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            {
                match (&(abi), &(ExternAbi::LlvmIntrinsic)) {
                    (left_val, right_val) => {
                        if *left_val == *right_val {
                            let kind = ::core::panicking::AssertKind::Ne;
                            ::core::panicking::assert_failed(kind, &*left_val,
                                &*right_val,
                                ::core::option::Option::Some(format_args!("fn_abi_of_instance should not be called on LLVM intrinsics")));
                        }
                    }
                }
            };
            if abi.is_rustic_abi() {
                fn_abi.adjust_for_rust_abi(cx);
            } else { fn_abi.adjust_for_foreign_abi(cx, abi); }
        }
    }
}#[tracing::instrument(level = "trace", skip(cx))]
624fn fn_abi_adjust_for_abi<'tcx>(
625    cx: &LayoutCx<'tcx>,
626    fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>,
627    abi: ExternAbi,
628) {
629    assert_ne!(
630        abi,
631        ExternAbi::LlvmIntrinsic,
632        "fn_abi_of_instance should not be called on LLVM intrinsics"
633    );
634
635    if abi.is_rustic_abi() {
636        fn_abi.adjust_for_rust_abi(cx);
637    } else {
638        fn_abi.adjust_for_foreign_abi(cx, abi);
639    }
640}
641
642{}
#[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("fn_abi_adjust_for_deduced_attrs",
                                    "rustc_ty_utils::abi", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(642u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("fn_abi")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("fn_abi");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("abi")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("abi");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("fn_def_id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("fn_def_id");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_abi)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&abi)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fn_def_id)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: &'tcx FnAbi<'tcx, Ty<'tcx>> =
                loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = cx.tcx();
            let deduced =
                if abi.is_rustic_abi() {
                    tcx.deduced_param_attrs(fn_def_id)
                } else { &[] };
            if deduced.is_empty() {
                fn_abi
            } else {
                let mut fn_abi = fn_abi.clone();
                apply_deduced_attributes(cx, deduced, 0, &mut fn_abi.ret);
                for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
                    apply_deduced_attributes(cx, deduced, arg_idx + 1, arg);
                }
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs:661",
                                        "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                        ::tracing_core::__macro_support::Option::Some(661u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                        ::tracing_core::field::FieldSet::new(&["message"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("fn_abi_adjust_for_deduced_attrs = {0:?}",
                                                                    fn_abi) as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
                fn_abi_sanity_check(cx, &fn_abi, abi);
                tcx.arena.alloc(fn_abi)
            }
        }
    }
}#[tracing::instrument(level = "trace", skip(cx))]
643fn fn_abi_adjust_for_deduced_attrs<'tcx>(
644    cx: &LayoutCx<'tcx>,
645    fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
646    abi: ExternAbi,
647    fn_def_id: DefId,
648) -> &'tcx FnAbi<'tcx, Ty<'tcx>> {
649    let tcx = cx.tcx();
650    // Look up the deduced parameter attributes for this function, if we have its def ID.
651    // We'll tag its parameters with those attributes as appropriate.
652    let deduced = if abi.is_rustic_abi() { tcx.deduced_param_attrs(fn_def_id) } else { &[] };
653    if deduced.is_empty() {
654        fn_abi
655    } else {
656        let mut fn_abi = fn_abi.clone();
657        apply_deduced_attributes(cx, deduced, 0, &mut fn_abi.ret);
658        for (arg_idx, arg) in fn_abi.args.iter_mut().enumerate() {
659            apply_deduced_attributes(cx, deduced, arg_idx + 1, arg);
660        }
661        debug!("fn_abi_adjust_for_deduced_attrs = {:?}", fn_abi);
662        fn_abi_sanity_check(cx, &fn_abi, abi);
663        tcx.arena.alloc(fn_abi)
664    }
665}
666
667/// Apply deduced optimization attributes to a parameter using an indirect pass mode.
668///
669/// `deduced` is a possibly truncated list of deduced attributes for a return place and arguments.
670/// `idx` the index of the parameter on the list (0 for a return place, and 1.. for arguments).
671fn apply_deduced_attributes<'tcx>(
672    cx: &LayoutCx<'tcx>,
673    deduced: &[DeducedParamAttrs],
674    idx: usize,
675    arg: &mut ArgAbi<'tcx, Ty<'tcx>>,
676) {
677    // Deduction is performed under the assumption of the indirection pass mode.
678    let PassMode::Indirect { ref mut attrs, .. } = arg.mode else {
679        return;
680    };
681    // The default values at the tail of the list are not encoded.
682    let Some(deduced) = deduced.get(idx) else {
683        return;
684    };
685    if deduced.read_only(cx.tcx(), cx.typing_env, arg.layout.ty) {
686        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs:686",
                        "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                        ::tracing_core::__macro_support::Option::Some(686u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("added deduced ReadOnly attribute")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("added deduced ReadOnly attribute");
687        attrs.regular.insert(ArgAttribute::ReadOnly);
688    }
689    if deduced.captures_none(cx.tcx(), cx.typing_env, arg.layout.ty) {
690        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs:690",
                        "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                        ::tracing_core::__macro_support::Option::Some(690u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("added deduced CapturesNone attribute")
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("added deduced CapturesNone attribute");
691        attrs.regular.insert(ArgAttribute::CapturesNone);
692    }
693}
694
695{}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_thin_self_ptr",
                                    "rustc_ty_utils::abi", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/822182db4c4a1827256881d8c7aa685f0bcf2b11/compiler/rustc_ty_utils/src/abi.rs"),
                                    ::tracing_core::__macro_support::Option::Some(695u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ty_utils::abi"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("layout")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("layout");
                                                        NAME.as_str()
                                                    }], ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&layout)
                                                            as &dyn ::tracing::field::Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: TyAndLayout<'tcx> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = cx.tcx();
            let wide_pointer_ty =
                if layout.is_unsized() {
                    Ty::new_mut_ptr(tcx, layout.ty)
                } else {
                    match layout.backend_repr {
                        BackendRepr::ScalarPair { .. } | BackendRepr::Scalar(..) =>
                            (),
                        _ =>
                            ::rustc_span::macros::bug_impl(None,
                                format_args!("receiver type has unsupported layout: {0:?}",
                                    layout), Location::caller()),
                    }
                    let mut wide_pointer_layout = layout;
                    while !wide_pointer_layout.ty.is_raw_ptr() &&
                            !wide_pointer_layout.ty.is_ref() {
                        wide_pointer_layout =
                            wide_pointer_layout.non_1zst_field(cx).expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type").1
                    }
                    wide_pointer_layout.ty
                };
            let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
            TyAndLayout {
                ty: wide_pointer_ty,
                ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap()
            }
        }
    }
}#[tracing::instrument(level = "debug", skip(cx))]
696fn make_thin_self_ptr<'tcx>(
697    cx: &(impl HasTyCtxt<'tcx> + HasTypingEnv<'tcx>),
698    layout: TyAndLayout<'tcx>,
699) -> TyAndLayout<'tcx> {
700    let tcx = cx.tcx();
701    let wide_pointer_ty = if layout.is_unsized() {
702        // unsized `self` is passed as a pointer to `self`
703        // FIXME (mikeyhew) change this to use &own if it is ever added to the language
704        Ty::new_mut_ptr(tcx, layout.ty)
705    } else {
706        match layout.backend_repr {
707            BackendRepr::ScalarPair { .. } | BackendRepr::Scalar(..) => (),
708            _ => bug!("receiver type has unsupported layout: {:?}", layout),
709        }
710
711        // In the case of Rc<Self>, we need to explicitly pass a *mut RcInner<Self>
712        // with a Scalar (not ScalarPair) ABI. This is a hack that is understood
713        // elsewhere in the compiler as a method on a `dyn Trait`.
714        // To get the type `*mut RcInner<Self>`, we just keep unwrapping newtypes until we
715        // get a built-in pointer type
716        let mut wide_pointer_layout = layout;
717        while !wide_pointer_layout.ty.is_raw_ptr() && !wide_pointer_layout.ty.is_ref() {
718            wide_pointer_layout = wide_pointer_layout
719                .non_1zst_field(cx)
720                .expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type")
721                .1
722        }
723
724        wide_pointer_layout.ty
725    };
726
727    // we now have a type like `*mut RcInner<dyn Trait>`
728    // change its layout to that of `*mut ()`, a thin pointer, but keep the same type
729    // this is understood as a special case elsewhere in the compiler
730    let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);
731
732    TyAndLayout {
733        ty: wide_pointer_ty,
734
735        // NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
736        // should always work because the type is always `*mut ()`.
737        ..tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(unit_ptr_ty)).unwrap()
738    }
739}