Skip to main content

rustc_mir_transform/
shim.rs

1use std::{assert_matches, fmt, iter};
2
3use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx};
4use rustc_attr_ir::lang_items::LangItem;
5use rustc_hir as hir;
6use rustc_hir::def_id::DefId;
7use rustc_index::{Idx, IndexVec};
8use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
9use rustc_middle::mir::*;
10use rustc_middle::query::Providers;
11use rustc_middle::ty::{
12    self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt, Unnormalized,
13};
14use rustc_span::{DUMMY_SP, Span, Spanned, bug, dummy_spanned, span_bug};
15use tracing::{debug, instrument};
16
17use crate::deref_separator::deref_finder;
18use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
19use crate::patch::MirPatch;
20use crate::{
21    abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, inline, instsimplify,
22    mentioned_items, pass_manager as pm, remove_noop_landing_pads, run_optimization_passes,
23    simplify,
24};
25
26mod async_destructor_ctor;
27
28pub(super) fn provide(providers: &mut Providers) {
29    providers.mir_shims = |tcx, shim| tcx.arena.alloc(make_shim(tcx, shim));
30}
31
32fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> {
33    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:33",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(33u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?})",
                                                    shim) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?})", shim);
34
35    let mut result = match shim {
36        ty::ShimKind::VTable(def_id) => {
37            let adjustment = Adjustment::Deref { source: DerefSource::MutPtr };
38            build_call_shim(tcx, shim, Some(adjustment), CallKind::Direct(def_id))
39        }
40        ty::ShimKind::FnPtr(def_id, ty) => {
41            let trait_ = tcx.parent(def_id);
42            // Supports `Fn` or `async Fn` traits.
43            let adjustment = match tcx
44                .fn_trait_kind_from_def_id(trait_)
45                .or_else(|| tcx.async_fn_trait_kind_from_def_id(trait_))
46            {
47                Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
48                Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef },
49                Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef },
50                None => ::rustc_span::macros::bug_impl(None,
    format_args!("fn pointer {0:?} is not an fn", ty), Location::caller())bug!("fn pointer {:?} is not an fn", ty),
51            };
52
53            build_call_shim(tcx, shim, Some(adjustment), CallKind::Indirect(ty))
54        }
55        // We are generating a call back to our def-id, which the
56        // codegen backend knows to turn to an actual call, be it
57        // a virtual call, or a direct call to a function for which
58        // indirect calls must be codegen'd differently than direct ones
59        // (such as `#[track_caller]`).
60        ty::ShimKind::Reify(def_id, _) => {
61            build_call_shim(tcx, shim, None, CallKind::Direct(def_id))
62        }
63        ty::ShimKind::ClosureOnce { call_once: _, closure: _, track_caller: _ } => {
64            let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP);
65            let call_mut = tcx
66                .associated_items(fn_mut)
67                .in_definition_order()
68                .find(|it| it.is_fn())
69                .unwrap()
70                .def_id;
71
72            build_call_shim(tcx, shim, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
73        }
74
75        ty::ShimKind::ConstructCoroutineInClosure { coroutine_closure_def_id, receiver_by_ref } => {
76            build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref)
77        }
78
79        ty::ShimKind::DropGlue(def_id, ty) => {
80            // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
81            // of this function. Is this intentional?
82            if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) {
83                let coroutine_body = tcx.optimized_mir(coroutine_def_id);
84
85                let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
86                else {
87                    ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
    Location::caller())bug!()
88                };
89
90                // If this is a regular coroutine, grab its drop shim. If this is a coroutine
91                // that comes from a coroutine-closure, and the kind ty differs from the "maximum"
92                // kind that it supports, then grab the appropriate drop shim. This ensures that
93                // the future returned by `<[coroutine-closure] as AsyncFnOnce>::call_once` will
94                // drop the coroutine-closure's upvars.
95                let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
96                    coroutine_body.coroutine_drop().unwrap()
97                } else {
98                    {
    match (&args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
            &ty::ClosureKind::FnOnce) {
        (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);
            }
        }
    }
};assert_eq!(
99                        args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
100                        ty::ClosureKind::FnOnce
101                    );
102                    tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id))
103                        .coroutine_drop()
104                        .unwrap()
105                };
106
107                let mut body =
108                    EarlyBinder::bind(tcx, body.clone()).instantiate(tcx, args).skip_norm_wip();
109                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:109",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(109u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = {1:?}",
                                                    shim, body) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
110
111                pm::run_passes(
112                    tcx,
113                    &mut body,
114                    &[
115                        &mentioned_items::MentionedItems,
116                        &abort_unwinding_calls::AbortUnwindingCalls,
117                        &add_call_guards::CriticalCallEdges,
118                    ],
119                    Some(MirPhase::Runtime(RuntimePhase::Optimized)),
120                );
121
122                return body;
123            }
124
125            build_drop_shim(tcx, def_id, ty, ty::TypingEnv::post_analysis(tcx, def_id))
126        }
127        ty::ShimKind::ThreadLocal(..) => build_thread_local_shim(tcx, shim),
128        ty::ShimKind::Clone(def_id, ty) => build_clone_shim(tcx, def_id, ty),
129        ty::ShimKind::FnPtrAsPtr(def_id, ty) => build_fn_ptr_as_ptr_shim(tcx, def_id, ty),
130        ty::ShimKind::FnPtrFromPtr(def_id, ty) => build_fn_ptr_from_ptr_shim(tcx, def_id, ty),
131        ty::ShimKind::FutureDropPoll(def_id, proxy_ty, impl_ty) => {
132            let mut body =
133                async_destructor_ctor::build_future_drop_poll_shim(tcx, def_id, proxy_ty, impl_ty);
134
135            pm::run_passes(
136                tcx,
137                &mut body,
138                &[
139                    &mentioned_items::MentionedItems,
140                    &abort_unwinding_calls::AbortUnwindingCalls,
141                    &add_call_guards::CriticalCallEdges,
142                ],
143                Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
144            );
145            run_optimization_passes(tcx, &mut body);
146            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:146",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(146u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = {1:?}",
                                                    shim, body) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
147            return body;
148        }
149        ty::ShimKind::AsyncDropGlue(def_id, ty) => {
150            let mut body = async_destructor_ctor::build_async_drop_shim(tcx, def_id, ty);
151
152            // Main pass required here is StateTransform to convert sync drop ladder
153            // into coroutine.
154            // Others are minimal passes as for sync drop glue shim
155            pm::run_passes_no_validate(
156                tcx,
157                &mut body,
158                &[
159                    &mentioned_items::MentionedItems,
160                    &abort_unwinding_calls::AbortUnwindingCalls,
161                    &add_call_guards::CriticalCallEdges,
162                    &simplify::SimplifyCfg::MakeShim,
163                    &crate::coroutine::StateTransform,
164                ],
165                Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
166            );
167            run_optimization_passes(tcx, &mut body);
168            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:168",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(168u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = {1:?}",
                                                    shim, body) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
169            return body;
170        }
171
172        ty::ShimKind::AsyncDropGlueCtor(def_id, ty) => {
173            let body = async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty);
174            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:174",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(174u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = {1:?}",
                                                    shim, body) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
175            return body;
176        }
177    };
178    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:178",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(178u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = untransformed {1:?}",
                                                    shim, result) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = untransformed {:?}", shim, result);
179
180    deref_finder(tcx, &mut result, false);
181
182    // We don't validate MIR here because the shims may generate code that's
183    // only valid in a `PostAnalysis` param-env. However, since we do initial
184    // validation with the MirBuilt phase, which uses a user-facing param-env.
185    // This causes validation errors when TAITs are involved.
186    pm::run_passes_no_validate(
187        tcx,
188        &mut result,
189        &[
190            &mentioned_items::MentionedItems,
191            &add_moves_for_packed_drops::AddMovesForPackedDrops,
192            &remove_noop_landing_pads::RemoveNoopLandingPads,
193            &simplify::SimplifyCfg::MakeShim,
194            &instsimplify::InstSimplify::BeforeInline,
195            // Perform inlining of `#[rustc_force_inline]`-annotated callees.
196            &inline::ForceInline,
197            &abort_unwinding_calls::AbortUnwindingCalls,
198            &add_call_guards::CriticalCallEdges,
199        ],
200        Some(MirPhase::Runtime(RuntimePhase::Optimized)),
201    );
202
203    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:203",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(203u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("make_shim({0:?}) = {1:?}",
                                                    shim, result) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", shim, result);
204
205    result
206}
207
208#[derive(#[automatically_derived]impl ::core::marker::Copy for DerefSource { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for DerefSource {
}
#[automatically_derived]impl ::core::clone::Clone for DerefSource {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for DerefSource {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                DerefSource::ImmRef => "ImmRef",
                DerefSource::MutRef => "MutRef",
                DerefSource::MutPtr => "MutPtr",
            })
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    DerefSource {
}
#[automatically_derived]impl ::core::cmp::PartialEq for DerefSource {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq)]
209enum DerefSource {
210    /// `fn shim(&self) { inner(*self )}`.
211    ImmRef,
212    /// `fn shim(&mut self) { inner(*self )}`.
213    MutRef,
214    /// `fn shim(*mut self) { inner(*self )}`.
215    MutPtr,
216}
217
218#[derive(#[automatically_derived]impl ::core::marker::Copy for Adjustment { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl ::core::clone::TrivialClone
    for Adjustment {
}
#[automatically_derived]impl ::core::clone::Clone for Adjustment {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<DerefSource>;
        *self
    }
}Clone, #[automatically_derived]impl ::core::fmt::Debug for Adjustment {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Identity =>
                ::core::fmt::Formatter::write_str(f, "Identity"),
            Self::Deref { source: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Deref source", &__self_0),
            Self::RefMut => ::core::fmt::Formatter::write_str(f, "RefMut"),
        }
    }
}Debug, #[automatically_derived]impl ::core::marker::StructuralPartialEq for
    Adjustment {
}
#[automatically_derived]impl ::core::cmp::PartialEq for Adjustment {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Deref { source: __self_0 }, Self::Deref {
                    source: __arg1_0 }) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq)]
219enum Adjustment {
220    /// Pass the receiver as-is.
221    Identity,
222
223    /// We get passed a reference or a raw pointer to `self` and call the target with `*self`.
224    ///
225    /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it
226    /// (for `VTableShim`, which effectively is passed `&own Self`).
227    Deref { source: DerefSource },
228
229    /// We get passed `self: Self` and call the target with `&mut self`.
230    ///
231    /// In this case we need to ensure that the `Self` is dropped after the call, as the callee
232    /// won't do it for us.
233    RefMut,
234}
235
236#[derive(#[automatically_derived]impl<'tcx> ::core::marker::Copy for CallKind<'tcx> { }Copy, #[automatically_derived]#[doc(hidden)]unsafe impl<'tcx>
    ::core::clone::TrivialClone for CallKind<'tcx> {
}
#[automatically_derived]impl<'tcx> ::core::clone::Clone for CallKind<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
        let _: ::core::clone::AssertParamIsClone<DefId>;
        *self
    }
}Clone, #[automatically_derived]impl<'tcx> ::core::fmt::Debug for CallKind<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::Indirect(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Indirect", &__self_0),
            Self::Direct(__self_0) =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "Direct", &__self_0),
        }
    }
}Debug, #[automatically_derived]impl<'tcx> ::core::marker::StructuralPartialEq for
    CallKind<'tcx> {
}
#[automatically_derived]impl<'tcx> ::core::cmp::PartialEq for CallKind<'tcx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::Indirect(__self_0), Self::Indirect(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (Self::Direct(__self_0), Self::Direct(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
237enum CallKind<'tcx> {
238    /// Call the `FnPtr` that was passed as the receiver.
239    Indirect(Ty<'tcx>),
240
241    /// Call a known `FnDef`.
242    Direct(DefId),
243}
244
245fn local_decls_for_sig<'tcx>(
246    sig: &ty::FnSig<'tcx>,
247    span: Span,
248) -> IndexVec<Local, LocalDecl<'tcx>> {
249    iter::once(LocalDecl::new(sig.output(), span))
250        .chain(sig.inputs().iter().map(|ity| LocalDecl::new(*ity, span).immutable()))
251        .collect()
252}
253
254/// Builds the drop glue for the provided type. The `def_id` is that of `core::ptr::drop_glue`.
255///
256/// Inside rustc this is only called on a monomorphic type, but we expose the function for
257/// rustc_driver writers to be able to generate drop glue for a polymorphic type.
258pub fn build_drop_shim<'tcx>(
259    tcx: TyCtxt<'tcx>,
260    def_id: DefId,
261    ty: Option<Ty<'tcx>>,
262    typing_env: ty::TypingEnv<'tcx>,
263) -> Body<'tcx> {
264    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:264",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(264u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("build_drop_shim(def_id={0:?}, ty={1:?})",
                                                    def_id, ty) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
265
266    if !!#[allow(non_exhaustive_omitted_patterns)] match ty {
                Some(ty) if ty.is_coroutine() => true,
                _ => false,
            } {
    ::core::panicking::panic("assertion failed: !matches!(ty, Some(ty) if ty.is_coroutine())")
};assert!(!matches!(ty, Some(ty) if ty.is_coroutine()));
267
268    let args = if let Some(ty) = ty {
269        tcx.mk_args(&[ty.into()])
270    } else {
271        GenericArgs::identity_for_item(tcx, def_id)
272    };
273    let sig = tcx.fn_sig(def_id).instantiate(tcx, args).skip_norm_wip();
274    let sig = tcx.instantiate_bound_regions_with_erased(sig);
275    let span = tcx.def_span(def_id);
276
277    let source_info = SourceInfo::outermost(span);
278
279    let return_block = BasicBlock::new(1);
280    let mut blocks = IndexVec::with_capacity(2);
281    let block = |blocks: &mut IndexVec<_, _>, kind| -> BasicBlock {
282        blocks.push(BasicBlockData::new(Terminator { source_info, kind }, false))
283    };
284    if ty.is_some() {
285        block(&mut blocks, TerminatorKind::goto(return_block));
286    }
287    let ret = block(&mut blocks, TerminatorKind::Return);
288    blocks[ret].statements.push(Statement::new(
289        source_info,
290        StatementKind::Assign(Box::new((
291            Place::return_place(),
292            Rvalue::Use(Operand::zero_sized_constant(tcx.types.unit, span), WithRetag::Yes),
293        ))),
294    ));
295
296    let source = MirSource::from_shim(ty::ShimKind::DropGlue(def_id, ty));
297    let mut body =
298        new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
299
300    let Some(ty) = ty else {
301        return body;
302    };
303
304    let dropee_ptr = Place::from(Local::arg(0));
305
306    if let ty::Array(ety, _len) = *ty.kind() {
307        // Don't write out the elaboration for each array type.
308        // Instead, just delegate to the slice version.
309        let slice_ty = Ty::new_slice(tcx, ety);
310        let mut_slice_ty = Ty::new_ref(tcx, tcx.lifetimes.re_erased, slice_ty, ty::Mutability::Mut);
311        let erased_local = body.local_decls.push(LocalDecl::new(mut_slice_ty, span));
312
313        let start = &mut body.basic_blocks_mut()[START_BLOCK];
314        start.statements.push(Statement::new(
315            source_info,
316            StatementKind::Assign(Box::new((
317                Place::from(erased_local),
318                Rvalue::Cast(
319                    CastKind::PointerCoercion(
320                        ty::adjustment::PointerCoercion::Unsize,
321                        CoercionSource::Implicit,
322                    ),
323                    Operand::Move(dropee_ptr),
324                    mut_slice_ty,
325                ),
326            ))),
327        ));
328        start.terminator = Some(Terminator {
329            source_info,
330            kind: TerminatorKind::Call {
331                func: Operand::function_handle(
332                    tcx,
333                    def_id,
334                    &[ty::GenericArg::from(slice_ty)],
335                    span,
336                ),
337                args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]),
338                destination: Place::from(RETURN_PLACE),
339                target: Some(return_block),
340                unwind: UnwindAction::Continue,
341                call_source: CallSource::Misc,
342                fn_span: span,
343            },
344        });
345    } else {
346        let patch = {
347            let mut elaborator = DropShimElaborator {
348                body: &body,
349                patch: MirPatch::new(&body),
350                tcx,
351                typing_env,
352                produce_async_drops: false,
353            };
354            let dropee = tcx.mk_place_deref(dropee_ptr);
355            let resume_block = elaborator.patch.resume_block();
356            elaborate_drop(
357                &mut elaborator,
358                source_info,
359                dropee,
360                (),
361                return_block,
362                Unwind::To(resume_block),
363                START_BLOCK,
364                None,
365            );
366            elaborator.patch
367        };
368        patch.apply(&mut body);
369    }
370
371    body
372}
373
374fn new_body<'tcx>(
375    source: MirSource<'tcx>,
376    basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
377    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
378    arg_count: usize,
379    span: Span,
380) -> Body<'tcx> {
381    let mut body = Body::new(
382        source,
383        basic_blocks,
384        IndexVec::from_elem_n(
385            SourceScopeData {
386                span,
387                parent_scope: None,
388                inlined: None,
389                inlined_parent_scope: None,
390                local_data: ClearCrossCrate::Clear,
391            },
392            1,
393        ),
394        local_decls,
395        IndexVec::new(),
396        arg_count,
397        ::alloc::vec::Vec::new()vec![],
398        span,
399        None,
400        // FIXME(compiler-errors): is this correct?
401        None,
402    );
403    // Shims do not directly mention any consts.
404    body.set_required_consts(Vec::new());
405    body
406}
407
408pub(super) struct DropShimElaborator<'a, 'tcx> {
409    pub body: &'a Body<'tcx>,
410    pub patch: MirPatch<'tcx>,
411    pub tcx: TyCtxt<'tcx>,
412    pub typing_env: ty::TypingEnv<'tcx>,
413    pub produce_async_drops: bool,
414}
415
416impl fmt::Debug for DropShimElaborator<'_, '_> {
417    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
418        f.debug_struct("DropShimElaborator").finish_non_exhaustive()
419    }
420}
421
422impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
423    type Path = ();
424
425    fn patch_ref(&self) -> &MirPatch<'tcx> {
426        &self.patch
427    }
428    fn patch(&mut self) -> &mut MirPatch<'tcx> {
429        &mut self.patch
430    }
431    fn body(&self) -> &'a Body<'tcx> {
432        self.body
433    }
434    fn tcx(&self) -> TyCtxt<'tcx> {
435        self.tcx
436    }
437    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
438        self.typing_env
439    }
440
441    fn allow_async_drops(&self) -> bool {
442        self.produce_async_drops
443    }
444
445    fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
446        match mode {
447            DropFlagMode::Shallow => {
448                // Drops for the contained fields are "shallow" and "static" - they will simply call
449                // the field's own drop glue.
450                DropStyle::Static
451            }
452            DropFlagMode::Deep => {
453                // The top-level drop is "deep" and "open" - it will be elaborated to a drop ladder
454                // dropping each field contained in the value.
455                DropStyle::Open
456            }
457        }
458    }
459
460    fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
461        None
462    }
463
464    fn drop_flags_for(&mut self, _path: Self::Path, _mode: DropFlagMode) -> Vec<Place<'tcx>> {
465        Vec::new()
466    }
467
468    fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option<Self::Path> {
469        None
470    }
471    fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
472        None
473    }
474    fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
475        Some(())
476    }
477    fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
478        None
479    }
480}
481
482fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> {
483    let def_id = shim.def_id();
484
485    let span = tcx.def_span(def_id);
486    let source_info = SourceInfo::outermost(span);
487
488    let blocks = IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [BasicBlockData::new_stmts(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                            [Statement::new(source_info,
                                        StatementKind::Assign(Box::new((Place::return_place(),
                                                    Rvalue::ThreadLocalRef(def_id)))))])),
                    Terminator { source_info, kind: TerminatorKind::Return },
                    false)]))vec![BasicBlockData::new_stmts(
489        vec![Statement::new(
490            source_info,
491            StatementKind::Assign(Box::new((
492                Place::return_place(),
493                Rvalue::ThreadLocalRef(def_id),
494            ))),
495        )],
496        Terminator { source_info, kind: TerminatorKind::Return },
497        false,
498    )]);
499
500    new_body(
501        MirSource::from_shim(shim),
502        blocks,
503        IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [LocalDecl::new(tcx.thread_local_ptr_ty(def_id), span)]))vec![LocalDecl::new(tcx.thread_local_ptr_ty(def_id), span)]),
504        0,
505        span,
506    )
507}
508
509/// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
510fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
511    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:511",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(511u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("build_clone_shim(def_id={0:?})",
                                                    def_id) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("build_clone_shim(def_id={:?})", def_id);
512
513    let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
514
515    let dest = Place::return_place();
516    let src = tcx.mk_place_deref(Place::from(Local::arg(0)));
517
518    match self_ty.kind() {
519        ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
520        ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
521        ty::CoroutineClosure(_, args) => {
522            builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
523        }
524        ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
525        ty::Coroutine(coroutine_def_id, args) => {
526            {
    match (&tcx.coroutine_movability(*coroutine_def_id),
            &hir::Movability::Movable) {
        (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);
            }
        }
    }
};assert_eq!(tcx.coroutine_movability(*coroutine_def_id), hir::Movability::Movable);
527            builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine())
528        }
529        _ => ::rustc_span::macros::bug_impl(None,
    format_args!("clone shim for `{0:?}` which is not `Copy` and is not an aggregate",
        self_ty), Location::caller())bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),
530    };
531
532    builder.into_mir()
533}
534
535struct CloneShimBuilder<'tcx> {
536    tcx: TyCtxt<'tcx>,
537    def_id: DefId,
538    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
539    blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
540    span: Span,
541    sig: ty::FnSig<'tcx>,
542}
543
544impl<'tcx> CloneShimBuilder<'tcx> {
545    fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
546        // we must instantiate the self_ty because it's
547        // otherwise going to be TySelf and we can't index
548        // or access fields of a Place of type TySelf.
549        let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip();
550        let sig = tcx.instantiate_bound_regions_with_erased(sig);
551        let span = tcx.def_span(def_id);
552
553        CloneShimBuilder {
554            tcx,
555            def_id,
556            local_decls: local_decls_for_sig(&sig, span),
557            blocks: IndexVec::new(),
558            span,
559            sig,
560        }
561    }
562
563    fn into_mir(self) -> Body<'tcx> {
564        let source =
565            MirSource::from_shim(ty::ShimKind::Clone(self.def_id, self.sig.inputs_and_output[0]));
566        new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
567    }
568
569    fn source_info(&self) -> SourceInfo {
570        SourceInfo::outermost(self.span)
571    }
572
573    fn block(
574        &mut self,
575        statements: Vec<Statement<'tcx>>,
576        kind: TerminatorKind<'tcx>,
577        is_cleanup: bool,
578    ) -> BasicBlock {
579        let source_info = self.source_info();
580        self.blocks.push(BasicBlockData::new_stmts(
581            statements,
582            Terminator { source_info, kind },
583            is_cleanup,
584        ))
585    }
586
587    /// Gives the index of an upcoming BasicBlock, with an offset.
588    /// offset=0 will give you the index of the next BasicBlock,
589    /// offset=1 will give the index of the next-to-next block,
590    /// offset=-1 will give you the index of the last-created block
591    fn block_index_offset(&self, offset: usize) -> BasicBlock {
592        BasicBlock::new(self.blocks.len() + offset)
593    }
594
595    fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
596        Statement::new(self.source_info(), kind)
597    }
598
599    fn copy_shim(&mut self) {
600        let rcvr = self.tcx.mk_place_deref(Place::from(Local::arg(0)));
601        let ret_statement = self.make_statement(StatementKind::Assign(Box::new((
602            Place::return_place(),
603            Rvalue::Use(Operand::Copy(rcvr), WithRetag::Yes),
604        ))));
605        self.block(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [ret_statement]))vec![ret_statement], TerminatorKind::Return, false);
606    }
607
608    fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
609        let span = self.span;
610        let mut local = LocalDecl::new(ty, span);
611        if mutability.is_not() {
612            local = local.immutable();
613        }
614        Place::from(self.local_decls.push(local))
615    }
616
617    fn make_clone_call(
618        &mut self,
619        dest: Place<'tcx>,
620        src: Place<'tcx>,
621        ty: Ty<'tcx>,
622        next: BasicBlock,
623        cleanup: BasicBlock,
624    ) {
625        let tcx = self.tcx;
626
627        // `func == Clone::clone(&ty) -> ty`
628        let func_ty = tcx.type_of(self.def_id).instantiate(tcx, &[ty.into()]).skip_norm_wip();
629        let func = Operand::Constant(Box::new(ConstOperand {
630            span: self.span,
631            user_ty: None,
632            const_: Const::zero_sized(func_ty),
633        }));
634
635        let ref_loc =
636            self.make_place(Mutability::Not, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty));
637
638        // `let ref_loc: &ty = &src;`
639        let statement = self.make_statement(StatementKind::Assign(Box::new((
640            ref_loc,
641            Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src),
642        ))));
643
644        // `let loc = Clone::clone(ref_loc);`
645        self.block(
646            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [statement]))vec![statement],
647            TerminatorKind::Call {
648                func,
649                args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
650                destination: dest,
651                target: Some(next),
652                unwind: UnwindAction::Cleanup(cleanup),
653                call_source: CallSource::Normal,
654                fn_span: self.span,
655            },
656            false,
657        );
658    }
659
660    fn clone_fields<I>(
661        &mut self,
662        dest: Place<'tcx>,
663        src: Place<'tcx>,
664        target: BasicBlock,
665        mut unwind: BasicBlock,
666        tys: I,
667    ) -> BasicBlock
668    where
669        I: IntoIterator<Item = Ty<'tcx>>,
670    {
671        // For an iterator of length n, create 2*n + 1 blocks.
672        for (i, ity) in tys.into_iter().enumerate() {
673            // Each iteration creates two blocks, referred to here as block 2*i and block 2*i + 1.
674            //
675            // Block 2*i attempts to clone the field. If successful it branches to 2*i + 2 (the
676            // next clone block). If unsuccessful it branches to the previous unwind block, which
677            // is initially the `unwind` argument passed to this function.
678            //
679            // Block 2*i + 1 is the unwind block for this iteration. It drops the cloned value
680            // created by block 2*i. We store this block in `unwind` so that the next clone block
681            // will unwind to it if cloning fails.
682
683            let field = FieldIdx::new(i);
684            let src_field = self.tcx.mk_place_field(src, field, ity);
685
686            let dest_field = self.tcx.mk_place_field(dest, field, ity);
687
688            let next_unwind = self.block_index_offset(1);
689            let next_block = self.block_index_offset(2);
690            self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
691            self.block(
692                ::alloc::vec::Vec::new()vec![],
693                TerminatorKind::Drop {
694                    place: dest_field,
695                    target: unwind,
696                    unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
697                    replace: false,
698                    drop: None,
699                },
700                /* is_cleanup */ true,
701            );
702            unwind = next_unwind;
703        }
704        // If all clones succeed then we end up here.
705        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::goto(target), false);
706        unwind
707    }
708
709    fn tuple_like_shim(
710        &mut self,
711        dest: Place<'tcx>,
712        src: Place<'tcx>,
713        tys: &'tcx ty::List<Ty<'tcx>>,
714    ) {
715        if tys.is_empty() {
716            // With no fields to clone, initialize the return local directly.
717            self.copy_shim();
718            return;
719        }
720
721        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::goto(self.block_index_offset(3)), false);
722        let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
723        let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
724
725        let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
726    }
727
728    fn coroutine_shim(
729        &mut self,
730        dest: Place<'tcx>,
731        src: Place<'tcx>,
732        coroutine_def_id: DefId,
733        args: CoroutineArgs<TyCtxt<'tcx>>,
734    ) {
735        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::goto(self.block_index_offset(3)), false);
736        let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
737        // This will get overwritten with a switch once we know the target blocks
738        let switch = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
739        let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
740        let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
741        let unreachable = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
742        let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count());
743        for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() {
744            let variant_index = VariantIdx::new(index);
745            let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
746            let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
747            let clone_block = self.block_index_offset(1);
748            let start_block = self.block(
749                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [self.make_statement(StatementKind::SetDiscriminant {
                        place: Box::new(Place::return_place()),
                        variant_index,
                    })]))vec![self.make_statement(StatementKind::SetDiscriminant {
750                    place: Box::new(Place::return_place()),
751                    variant_index,
752                })],
753                TerminatorKind::goto(clone_block),
754                false,
755            );
756            cases.push((index as u128, start_block));
757            let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
758        }
759        let discr_ty = args.discr_ty(self.tcx);
760        let temp = self.make_place(Mutability::Mut, discr_ty);
761        let rvalue = Rvalue::Discriminant(src);
762        let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
763        match &mut self.blocks[switch] {
764            BasicBlockData { statements, terminator: Some(Terminator { kind, .. }), .. } => {
765                statements.push(statement);
766                *kind = TerminatorKind::SwitchInt {
767                    discr: Operand::Move(temp),
768                    targets: SwitchTargets::new(cases.into_iter(), unreachable),
769                };
770            }
771            BasicBlockData { terminator: None, .. } => ::core::panicking::unreachable_default_msg()unreachable!(),
772        }
773    }
774}
775
776/// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`,
777/// first adjusting its first argument according to `rcvr_adjustment`.
778{}
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("build_call_shim",
                                "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                                ::tracing_core::__macro_support::Option::Some(778u32),
                                ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                                ::tracing_core::field::FieldSet::new(&[{
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("shim")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("shim");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("rcvr_adjustment")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("rcvr_adjustment");
                                                    NAME.as_str()
                                                },
                                                {
                                                    const NAME:
                                                        ::tracing::__macro_support::FieldName<{
                                                            ::tracing::__macro_support::FieldName::len("call_kind")
                                                        }> =
                                                        ::tracing::__macro_support::FieldName::new("call_kind");
                                                    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(&shim)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rcvr_adjustment)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&call_kind)
                                                        as &dyn ::tracing::field::Value))])
                        })
            } else {
                let span =
                    ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                {};
                span
            }
        };
    __tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
    (move ||
                {

                    #[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: Body<'tcx> = loop {};
                        return __tracing_attr_fake_return;
                    }
                    {
                        let (sig_args, untuple_args) =
                            if let ty::ShimKind::FnPtr(_, ty) = shim {
                                let sig =
                                    tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
                                let untuple_args = sig.inputs();
                                let arg_tup = Ty::new_tup(tcx, untuple_args);
                                (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
                            } else { (None, None) };
                        let def_id = shim.def_id();
                        let sig = tcx.fn_sig(def_id);
                        let sig =
                            sig.map_bound(|sig|
                                    tcx.instantiate_bound_regions_with_erased(sig));
                        {
                            match (&sig_args.is_some(),
                                    &!shim.has_polymorphic_mir_body()) {
                                (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 mut sig =
                            if let Some(sig_args) = sig_args {
                                sig.instantiate(tcx, &sig_args).skip_norm_wip()
                            } else { sig.instantiate_identity().skip_norm_wip() };
                        if let CallKind::Indirect(fnty) = call_kind {
                            let mut inputs_and_output = sig.inputs_and_output.to_vec();
                            {
                                match (&inputs_and_output.len(), &3) {
                                    (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 self_arg = &mut inputs_and_output[0];
                            *self_arg =
                                match rcvr_adjustment.unwrap() {
                                    Adjustment::Identity => fnty,
                                    Adjustment::Deref { source } =>
                                        match source {
                                            DerefSource::ImmRef =>
                                                Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
                                            DerefSource::MutRef =>
                                                Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
                                            DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
                                        },
                                    Adjustment::RefMut =>
                                        ::rustc_span::macros::bug_impl(None,
                                            format_args!("`RefMut` is never used with indirect calls: {0:?}",
                                                shim), Location::caller()),
                                };
                            sig.inputs_and_output =
                                tcx.mk_type_list(&inputs_and_output);
                        }
                        if let ty::ShimKind::VTable(..) = shim {
                            let mut inputs_and_output = sig.inputs_and_output.to_vec();
                            let self_arg = &mut inputs_and_output[0];
                            if true {
                                if !(tcx.generics_of(def_id).has_self &&
                                            *self_arg == tcx.types.self_param) {
                                    ::core::panicking::panic("assertion failed: tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param")
                                };
                            };
                            *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
                            sig.inputs_and_output =
                                tcx.mk_type_list(&inputs_and_output);
                        }
                        let span = tcx.def_span(def_id);
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:853",
                                                "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                                                ::tracing_core::__macro_support::Option::Some(853u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                                                ::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()
                                                                }], ::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(&::tracing::field::debug(&sig)
                                                                    as &dyn ::tracing::field::Value))])
                                    });
                            } else { ; }
                        };
                        let mut local_decls = local_decls_for_sig(&sig, span);
                        let source_info = SourceInfo::outermost(span);
                        let destination = Place::return_place();
                        let rcvr_place =
                            ||
                                {
                                    if !rcvr_adjustment.is_some() {
                                        ::core::panicking::panic("assertion failed: rcvr_adjustment.is_some()")
                                    };
                                    Place::from(Local::arg(0))
                                };
                        let mut statements = ::alloc::vec::Vec::new();
                        let rcvr =
                            rcvr_adjustment.map(|rcvr_adjustment|
                                    match rcvr_adjustment {
                                        Adjustment::Identity => Operand::Move(rcvr_place()),
                                        Adjustment::Deref { source: _ } =>
                                            Operand::Move(tcx.mk_place_deref(rcvr_place())),
                                        Adjustment::RefMut => {
                                            let ref_rcvr =
                                                local_decls.push(LocalDecl::new(Ty::new_mut_ref(tcx,
                                                                tcx.lifetimes.re_erased, sig.inputs()[0]),
                                                            span).immutable());
                                            let borrow_kind =
                                                BorrowKind::Mut { kind: MutBorrowKind::Default };
                                            statements.push(Statement::new(source_info,
                                                    StatementKind::Assign(Box::new((Place::from(ref_rcvr),
                                                                Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind,
                                                                    rcvr_place()))))));
                                            Operand::Move(Place::from(ref_rcvr))
                                        }
                                    });
                        let (callee, mut args) =
                            match call_kind {
                                CallKind::Indirect(_) =>
                                    (rcvr.unwrap(), ::alloc::vec::Vec::new()),
                                CallKind::Direct(def_id) => {
                                    let ty =
                                        tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
                                    (Operand::Constant(Box::new(ConstOperand {
                                                    span,
                                                    user_ty: None,
                                                    const_: Const::zero_sized(ty),
                                                })), rcvr.into_iter().collect::<Vec<_>>())
                                }
                            };
                        let mut arg_range = 0..sig.inputs().len();
                        if rcvr_adjustment.is_some() { arg_range.start += 1; }
                        if untuple_args.is_some() { arg_range.end -= 1; }
                        args.extend(arg_range.map(|i|
                                    Operand::Move(Place::from(Local::arg(i)))));
                        if let Some(untuple_args) = untuple_args {
                            let tuple_arg = Local::arg(sig.inputs().len() - 1);
                            args.extend(untuple_args.iter().enumerate().map(|(i, ity)|
                                        {
                                            Operand::Move(tcx.mk_place_field(Place::from(tuple_arg),
                                                    FieldIdx::new(i), *ity))
                                        }));
                        }
                        let n_blocks =
                            if let Some(Adjustment::RefMut) = rcvr_adjustment {
                                5
                            } else { 2 };
                        let mut blocks = IndexVec::with_capacity(n_blocks);
                        let block =
                            |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup|
                                {
                                    blocks.push(BasicBlockData::new_stmts(statements,
                                            Terminator { source_info, kind }, is_cleanup))
                                };
                        let args =
                            args.into_iter().map(|a|
                                        Spanned { node: a, span: DUMMY_SP }).collect();
                        block(&mut blocks, statements,
                            TerminatorKind::Call {
                                func: callee,
                                args,
                                destination,
                                target: Some(BasicBlock::new(1)),
                                unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
                                    UnwindAction::Cleanup(BasicBlock::new(3))
                                } else { UnwindAction::Continue },
                                call_source: CallSource::Misc,
                                fn_span: span,
                            }, false);
                        if let Some(Adjustment::RefMut) = rcvr_adjustment {
                            block(&mut blocks, ::alloc::vec::Vec::new(),
                                TerminatorKind::Drop {
                                    place: rcvr_place(),
                                    target: BasicBlock::new(2),
                                    unwind: UnwindAction::Continue,
                                    replace: false,
                                    drop: None,
                                }, false);
                        }
                        let stmts = ::alloc::vec::Vec::new();
                        block(&mut blocks, stmts, TerminatorKind::Return, false);
                        if let Some(Adjustment::RefMut) = rcvr_adjustment {
                            block(&mut blocks, ::alloc::vec::Vec::new(),
                                TerminatorKind::Drop {
                                    place: rcvr_place(),
                                    target: BasicBlock::new(4),
                                    unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
                                    replace: false,
                                    drop: None,
                                }, true);
                            block(&mut blocks, ::alloc::vec::Vec::new(),
                                TerminatorKind::UnwindResume, true);
                        }
                        let mut body =
                            new_body(MirSource::from_shim(shim), blocks, local_decls,
                                sig.inputs().len(), span);
                        if let ExternAbi::RustCall = sig.abi() {
                            body.spread_arg = Some(Local::new(sig.inputs().len()));
                        }
                        body
                    }
                })();
{
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:778",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(778u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("return")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("return");
                                            NAME.as_str()
                                        }], ::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(&::tracing::field::debug(&x)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};
x;#[instrument(level = "debug", skip(tcx), ret)]
779fn build_call_shim<'tcx>(
780    tcx: TyCtxt<'tcx>,
781    shim: ty::ShimKind<'tcx>,
782    rcvr_adjustment: Option<Adjustment>,
783    call_kind: CallKind<'tcx>,
784) -> Body<'tcx> {
785    // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
786    // to instantiate into the signature of the shim. It is not necessary for users of this
787    // MIR body to perform further instantiations (see `InstanceKind::has_polymorphic_mir_body`).
788    let (sig_args, untuple_args) = if let ty::ShimKind::FnPtr(_, ty) = shim {
789        let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
790
791        let untuple_args = sig.inputs();
792
793        // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
794        let arg_tup = Ty::new_tup(tcx, untuple_args);
795
796        (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
797    } else {
798        (None, None)
799    };
800
801    let def_id = shim.def_id();
802
803    let sig = tcx.fn_sig(def_id);
804    let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
805
806    assert_eq!(sig_args.is_some(), !shim.has_polymorphic_mir_body());
807    let mut sig = if let Some(sig_args) = sig_args {
808        sig.instantiate(tcx, &sig_args).skip_norm_wip()
809    } else {
810        sig.instantiate_identity().skip_norm_wip()
811    };
812
813    if let CallKind::Indirect(fnty) = call_kind {
814        // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
815        // can only be an `FnDef` or `FnPtr`, but currently will be `Self` since the types come from
816        // the implemented `FnX` trait.
817
818        // Apply the opposite adjustment to the MIR input.
819        let mut inputs_and_output = sig.inputs_and_output.to_vec();
820
821        // Initial signature is `fn(&? Self, Args) -> Self::Output` where `Args` is a tuple of the
822        // fn arguments. `Self` may be passed via (im)mutable reference or by-value.
823        assert_eq!(inputs_and_output.len(), 3);
824
825        // `Self` is always the original fn type `ty`. The MIR call terminator is only defined for
826        // `FnDef` and `FnPtr` callees, not the `Self` type param.
827        let self_arg = &mut inputs_and_output[0];
828        *self_arg = match rcvr_adjustment.unwrap() {
829            Adjustment::Identity => fnty,
830            Adjustment::Deref { source } => match source {
831                DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
832                DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
833                DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
834            },
835            Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {shim:?}"),
836        };
837        sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
838    }
839
840    // FIXME: Avoid having to adjust the signature both here and in
841    // `fn_sig_for_fn_abi`.
842    if let ty::ShimKind::VTable(..) = shim {
843        // Modify fn(self, ...) to fn(self: *mut Self, ...)
844        let mut inputs_and_output = sig.inputs_and_output.to_vec();
845        let self_arg = &mut inputs_and_output[0];
846        debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
847        *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
848        sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
849    }
850
851    let span = tcx.def_span(def_id);
852
853    debug!(?sig);
854
855    let mut local_decls = local_decls_for_sig(&sig, span);
856    let source_info = SourceInfo::outermost(span);
857
858    let destination = Place::return_place();
859
860    let rcvr_place = || {
861        assert!(rcvr_adjustment.is_some());
862        Place::from(Local::arg(0))
863    };
864    let mut statements = vec![];
865
866    let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
867        Adjustment::Identity => Operand::Move(rcvr_place()),
868        Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())),
869        Adjustment::RefMut => {
870            // let rcvr = &mut rcvr;
871            let ref_rcvr = local_decls.push(
872                LocalDecl::new(
873                    Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, sig.inputs()[0]),
874                    span,
875                )
876                .immutable(),
877            );
878            let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
879            statements.push(Statement::new(
880                source_info,
881                StatementKind::Assign(Box::new((
882                    Place::from(ref_rcvr),
883                    Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
884                ))),
885            ));
886            Operand::Move(Place::from(ref_rcvr))
887        }
888    });
889
890    let (callee, mut args) = match call_kind {
891        // `FnPtr` call has no receiver. Args are untupled below.
892        CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
893
894        // `FnDef` call with optional receiver.
895        CallKind::Direct(def_id) => {
896            let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
897            (
898                Operand::Constant(Box::new(ConstOperand {
899                    span,
900                    user_ty: None,
901                    const_: Const::zero_sized(ty),
902                })),
903                rcvr.into_iter().collect::<Vec<_>>(),
904            )
905        }
906    };
907
908    let mut arg_range = 0..sig.inputs().len();
909
910    // Take the `self` ("receiver") argument out of the range (it's adjusted above).
911    if rcvr_adjustment.is_some() {
912        arg_range.start += 1;
913    }
914
915    // Take the last argument, if we need to untuple it (handled below).
916    if untuple_args.is_some() {
917        arg_range.end -= 1;
918    }
919
920    // Pass all of the non-special arguments directly.
921    args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::arg(i)))));
922
923    // Untuple the last argument, if we have to.
924    if let Some(untuple_args) = untuple_args {
925        let tuple_arg = Local::arg(sig.inputs().len() - 1);
926        args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
927            Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity))
928        }));
929    }
930
931    let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
932    let mut blocks = IndexVec::with_capacity(n_blocks);
933    let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
934        blocks.push(BasicBlockData::new_stmts(
935            statements,
936            Terminator { source_info, kind },
937            is_cleanup,
938        ))
939    };
940
941    // BB #0
942    let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
943    block(
944        &mut blocks,
945        statements,
946        TerminatorKind::Call {
947            func: callee,
948            args,
949            destination,
950            target: Some(BasicBlock::new(1)),
951            unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
952                UnwindAction::Cleanup(BasicBlock::new(3))
953            } else {
954                UnwindAction::Continue
955            },
956            call_source: CallSource::Misc,
957            fn_span: span,
958        },
959        false,
960    );
961
962    if let Some(Adjustment::RefMut) = rcvr_adjustment {
963        // BB #1 - drop for Self
964        block(
965            &mut blocks,
966            vec![],
967            TerminatorKind::Drop {
968                place: rcvr_place(),
969                target: BasicBlock::new(2),
970                unwind: UnwindAction::Continue,
971                replace: false,
972                drop: None,
973            },
974            false,
975        );
976    }
977    // BB #1/#2 - return
978    let stmts = vec![];
979    block(&mut blocks, stmts, TerminatorKind::Return, false);
980    if let Some(Adjustment::RefMut) = rcvr_adjustment {
981        // BB #3 - drop if closure panics
982        block(
983            &mut blocks,
984            vec![],
985            TerminatorKind::Drop {
986                place: rcvr_place(),
987                target: BasicBlock::new(4),
988                unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
989                replace: false,
990                drop: None,
991            },
992            /* is_cleanup */ true,
993        );
994
995        // BB #4 - resume
996        block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
997    }
998
999    let mut body =
1000        new_body(MirSource::from_shim(shim), blocks, local_decls, sig.inputs().len(), span);
1001
1002    if let ExternAbi::RustCall = sig.abi() {
1003        body.spread_arg = Some(Local::new(sig.inputs().len()));
1004    }
1005
1006    body
1007}
1008
1009pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
1010    if true {
    if !tcx.is_constructor(ctor_id) {
        ::core::panicking::panic("assertion failed: tcx.is_constructor(ctor_id)")
    };
};debug_assert!(tcx.is_constructor(ctor_id));
1011
1012    let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
1013
1014    // Normalize the sig.
1015    let sig = tcx
1016        .fn_sig(ctor_id)
1017        .instantiate_identity()
1018        .skip_norm_wip()
1019        .no_bound_vars()
1020        .expect("LBR in ADT constructor signature");
1021    let sig = tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(sig));
1022
1023    let ty::Adt(adt_def, args) = sig.output().kind() else {
1024        ::rustc_span::macros::bug_impl(None,
    format_args!("unexpected type for ADT ctor {0:?}", sig.output()),
    Location::caller());bug!("unexpected type for ADT ctor {:?}", sig.output());
1025    };
1026
1027    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:1027",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(1027u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("build_ctor: ctor_id={0:?} sig={1:?}",
                                                    ctor_id, sig) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
1028
1029    let span = tcx.def_span(ctor_id);
1030
1031    let local_decls = local_decls_for_sig(&sig, span);
1032
1033    let source_info = SourceInfo::outermost(span);
1034
1035    let variant_index =
1036        if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
1037
1038    // Generate the following MIR:
1039    //
1040    // (return as Variant).field0 = arg0;
1041    // (return as Variant).field1 = arg1;
1042    //
1043    // return;
1044    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs:1044",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(1044u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
                        ::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!("build_ctor: variant_index={0:?}",
                                                    variant_index) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("build_ctor: variant_index={:?}", variant_index);
1045
1046    let kind = AggregateKind::Adt(adt_def.did(), variant_index, *args, None, None);
1047    let variant = adt_def.variant(variant_index);
1048    let statement = Statement::new(
1049        source_info,
1050        StatementKind::Assign(Box::new((
1051            Place::return_place(),
1052            Rvalue::Aggregate(
1053                Box::new(kind),
1054                (0..variant.fields.len())
1055                    .map(|idx| Operand::Move(Place::from(Local::arg(idx))))
1056                    .collect(),
1057            ),
1058        ))),
1059    );
1060
1061    let start_block = BasicBlockData::new_stmts(
1062        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [statement]))vec![statement],
1063        Terminator { source_info, kind: TerminatorKind::Return },
1064        false,
1065    );
1066
1067    let source = MirSource::item(ctor_id);
1068    let mut body = new_body(
1069        source,
1070        IndexVec::from_elem_n(start_block, 1),
1071        local_decls,
1072        sig.inputs().len(),
1073        span,
1074    );
1075    // A constructor doesn't mention any other items (and we don't run the usual optimization passes
1076    // so this would otherwise not get filled).
1077    body.set_mentioned_items(Vec::new());
1078
1079    // We don't pass any passes here, we just force a phase change to `Optimized`.
1080    // Otherwise this bit of MIR will trigger assertions trying to detect MIR with an invalid phase.
1081    pm::run_passes_no_validate(
1082        tcx,
1083        &mut body,
1084        &[],
1085        Some(MirPhase::Runtime(RuntimePhase::Optimized)),
1086    );
1087
1088    body
1089}
1090
1091/// ```ignore (pseudo-impl)
1092/// impl FnPtr for fn(u32) {
1093///     fn addr(self) -> NonNull<Code> {
1094///         unsafe { transmute(self as *const Code)}
1095///     }
1096/// }
1097/// ```
1098fn build_fn_ptr_as_ptr_shim<'tcx>(
1099    tcx: TyCtxt<'tcx>,
1100    def_id: DefId,
1101    self_ty: Ty<'tcx>,
1102) -> Body<'tcx> {
1103    {
    match self_ty.kind() {
        ty::FnPtr(..) => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "ty::FnPtr(..)",
                ::core::option::Option::Some(format_args!("expected fn ptr, found {0}",
                        self_ty)));
        }
    }
};assert_matches!(self_ty.kind(), ty::FnPtr(..), "expected fn ptr, found {self_ty}");
1104
1105    let span = tcx.def_span(def_id);
1106    let nonnull_did = tcx.require_lang_item(LangItem::NonNull, span);
1107    let code_did = tcx.require_lang_item(LangItem::Code, span);
1108    let nonnull_ty = tcx
1109        .type_of(nonnull_did)
1110        .instantiate(
1111            tcx,
1112            &[ty::GenericArg::from(tcx.type_of(code_did).instantiate_identity().skip_norm_wip())],
1113        )
1114        .skip_norm_wip();
1115
1116    let Some(sig) =
1117        tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip().no_bound_vars()
1118    else {
1119        ::rustc_span::macros::bug_impl(Some(span),
    format_args!("FnPtr::as_ptr with bound vars for `{0}`", self_ty),
    Location::caller());span_bug!(span, "FnPtr::as_ptr with bound vars for `{self_ty}`");
1120    };
1121    let mut locals = local_decls_for_sig(&sig, span);
1122
1123    let source_info = SourceInfo::outermost(span);
1124
1125    let mut statements = ::alloc::vec::Vec::new()vec![];
1126    // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful
1127    // provenance.
1128    let raw_unit_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
1129    let cast_to_raw_rvalue =
1130        Rvalue::Cast(CastKind::FnPtrToPtr, Operand::Move(Place::from(Local::arg(0))), raw_unit_ptr);
1131    let raw_ptr = locals.push(LocalDecl::with_source_info(raw_unit_ptr, source_info)).into();
1132    statements.push(Statement::new(
1133        source_info,
1134        StatementKind::Assign(Box::new((raw_ptr, cast_to_raw_rvalue))),
1135    ));
1136
1137    let transmute_to_nonnull =
1138        Rvalue::Cast(CastKind::Transmute, Operand::Move(Place::from(raw_ptr)), nonnull_ty);
1139    statements.push(Statement::new(
1140        source_info,
1141        StatementKind::Assign(Box::new((Place::return_place(), transmute_to_nonnull))),
1142    ));
1143
1144    let start_block = BasicBlockData::new_stmts(
1145        statements,
1146        Terminator { source_info, kind: TerminatorKind::Return },
1147        false,
1148    );
1149    let source = MirSource::from_shim(ty::ShimKind::FnPtrAsPtr(def_id, self_ty));
1150    new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1151}
1152
1153fn build_fn_ptr_from_ptr_shim<'tcx>(
1154    tcx: TyCtxt<'tcx>,
1155    def_id: DefId,
1156    self_ty: Ty<'tcx>,
1157) -> Body<'tcx> {
1158    {
    match self_ty.kind() {
        ty::FnPtr(..) => {}
        ref left_val => {
            ::core::panicking::assert_matches_failed(left_val,
                "ty::FnPtr(..)",
                ::core::option::Option::Some(format_args!("expected fn ptr, found {0}",
                        self_ty)));
        }
    }
};assert_matches!(self_ty.kind(), ty::FnPtr(..), "expected fn ptr, found {self_ty}");
1159
1160    let span = tcx.def_span(def_id);
1161
1162    let Some(sig) =
1163        tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip().no_bound_vars()
1164    else {
1165        ::rustc_span::macros::bug_impl(Some(span),
    format_args!("FnPtr::as_ptr with bound vars for `{0}`", self_ty),
    Location::caller());span_bug!(span, "FnPtr::as_ptr with bound vars for `{self_ty}`");
1166    };
1167    let locals = local_decls_for_sig(&sig, span);
1168
1169    let source_info = SourceInfo::outermost(span);
1170
1171    let mut statements = ::alloc::vec::Vec::new()vec![];
1172    let transmute_to_self =
1173        Rvalue::Cast(CastKind::Transmute, Operand::Move(Place::from(Local::arg(0))), self_ty);
1174    statements.push(Statement::new(
1175        source_info,
1176        StatementKind::Assign(Box::new((Place::return_place(), transmute_to_self))),
1177    ));
1178
1179    let start_block = BasicBlockData::new_stmts(
1180        statements,
1181        Terminator { source_info, kind: TerminatorKind::Return },
1182        false,
1183    );
1184    let source = MirSource::from_shim(ty::ShimKind::FnPtrFromPtr(def_id, self_ty));
1185    new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1186}
1187
1188fn build_construct_coroutine_by_move_shim<'tcx>(
1189    tcx: TyCtxt<'tcx>,
1190    coroutine_closure_def_id: DefId,
1191    receiver_by_ref: bool,
1192) -> Body<'tcx> {
1193    let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity().skip_norm_wip();
1194    let mut self_local: Place<'tcx> = Local::arg(0).into();
1195    let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
1196        ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
    Location::caller());bug!();
1197    };
1198
1199    // We use `&Self` here because we only need to emit an ABI-compatible shim body,
1200    // rather than match the signature exactly (which might take `&mut self` instead).
1201    //
1202    // We adjust the `self_local` to be a deref since we want to copy fields out of
1203    // a reference to the closure.
1204    if receiver_by_ref {
1205        self_local = tcx.mk_place_deref(self_local);
1206        self_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, self_ty);
1207    }
1208
1209    let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
1210        tcx.mk_fn_sig(
1211            [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
1212            sig.to_coroutine_given_kind_and_upvars(
1213                tcx,
1214                args.as_coroutine_closure().parent_args(),
1215                tcx.coroutine_for_closure(coroutine_closure_def_id),
1216                ty::ClosureKind::FnOnce,
1217                tcx.lifetimes.re_erased,
1218                args.as_coroutine_closure().tupled_upvars_ty(),
1219                args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
1220            ),
1221            sig.fn_sig_kind,
1222        )
1223    });
1224    let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
1225    let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else {
1226        ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
    Location::caller());bug!();
1227    };
1228
1229    let span = tcx.def_span(coroutine_closure_def_id);
1230    let locals = local_decls_for_sig(&sig, span);
1231
1232    let mut fields = ::alloc::vec::Vec::new()vec![];
1233
1234    // Move all of the closure args.
1235    for idx in 1..sig.inputs().len() {
1236        fields.push(Operand::Move(Local::arg(idx).into()));
1237    }
1238
1239    for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
1240        if receiver_by_ref {
1241            // The only situation where it's possible is when we capture immuatable references,
1242            // since those don't need to be reborrowed with the closure's env lifetime. Since
1243            // references are always `Copy`, just emit a copy.
1244            if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Ref(_, _, hir::Mutability::Not) => true,
    _ => false,
}matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
1245                // This copy is only sound if it's a `&T`. This may be
1246                // reachable e.g. when eagerly computing the `Fn` instance
1247                // of an async closure that doesn't borrowck.
1248                tcx.dcx().delayed_bug(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("field should be captured by immutable ref if we have an `Fn` instance, but it was: {0}",
                ty))
    })format!(
1249                    "field should be captured by immutable ref if we have \
1250                    an `Fn` instance, but it was: {ty}"
1251                ));
1252            }
1253            fields.push(Operand::Copy(tcx.mk_place_field(
1254                self_local,
1255                FieldIdx::from_usize(idx),
1256                ty,
1257            )));
1258        } else {
1259            fields.push(Operand::Move(tcx.mk_place_field(
1260                self_local,
1261                FieldIdx::from_usize(idx),
1262                ty,
1263            )));
1264        }
1265    }
1266
1267    let source_info = SourceInfo::outermost(span);
1268    let rvalue = Rvalue::Aggregate(
1269        Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)),
1270        IndexVec::from_raw(fields),
1271    );
1272    let stmt = Statement::new(
1273        source_info,
1274        StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1275    );
1276    let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [stmt]))vec![stmt];
1277    let start_block = BasicBlockData::new_stmts(
1278        statements,
1279        Terminator { source_info, kind: TerminatorKind::Return },
1280        false,
1281    );
1282
1283    let source = MirSource::from_shim(ty::ShimKind::ConstructCoroutineInClosure {
1284        coroutine_closure_def_id,
1285        receiver_by_ref,
1286    });
1287
1288    let body =
1289        new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
1290
1291    let pass_name =
1292        if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" };
1293    if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) {
1294        dumper.dump_mir(&body);
1295    }
1296
1297    body
1298}