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_hir as hir;
5use rustc_hir::def_id::DefId;
6use rustc_hir::lang_items::LangItem;
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,
13};
14use rustc_middle::{bug, span_bug};
15use rustc_span::source_map::{Spanned, dummy_spanned};
16use rustc_span::{DUMMY_SP, Span};
17use tracing::{debug, instrument};
18
19use crate::deref_separator::deref_finder;
20use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
21use crate::patch::MirPatch;
22use crate::{
23    abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, inline, instsimplify,
24    mentioned_items, pass_manager as pm, remove_noop_landing_pads, run_optimization_passes,
25    simplify,
26};
27
28mod async_destructor_ctor;
29
30pub(super) fn provide(providers: &mut Providers) {
31    providers.mir_shims = make_shim;
32}
33
34// Replace Pin<&mut ImplCoroutine> accesses (_1.0) into Pin<&mut ProxyCoroutine> accesses
35struct FixProxyFutureDropVisitor<'tcx> {
36    tcx: TyCtxt<'tcx>,
37    replace_to: Local,
38}
39
40impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> {
41    fn tcx(&self) -> TyCtxt<'tcx> {
42        self.tcx
43    }
44
45    fn visit_place(
46        &mut self,
47        place: &mut Place<'tcx>,
48        _context: PlaceContext,
49        _location: Location,
50    ) {
51        if place.local == Local::from_u32(1) {
52            if place.projection.len() == 1 {
53                if !#[allow(non_exhaustive_omitted_patterns)] match place.projection.first() {
            Some(ProjectionElem::Field(FieldIdx::ZERO, _)) => true,
            _ => false,
        } {
    ::core::panicking::panic("assertion failed: matches!(place.projection.first(),\n    Some(ProjectionElem::Field(FieldIdx::ZERO, _)))")
};assert!(matches!(
54                    place.projection.first(),
55                    Some(ProjectionElem::Field(FieldIdx::ZERO, _))
56                ));
57                *place = Place::from(self.replace_to);
58            } else if place.projection.len() == 2 {
59                if !#[allow(non_exhaustive_omitted_patterns)] match place.projection[0] {
            ProjectionElem::Field(FieldIdx::ZERO, _) => true,
            _ => false,
        } {
    ::core::panicking::panic("assertion failed: matches!(place.projection[0], ProjectionElem::Field(FieldIdx::ZERO, _))")
};assert!(matches!(place.projection[0], ProjectionElem::Field(FieldIdx::ZERO, _)));
60                if !#[allow(non_exhaustive_omitted_patterns)] match place.projection[1] {
            ProjectionElem::Deref => true,
            _ => false,
        } {
    ::core::panicking::panic("assertion failed: matches!(place.projection[1], ProjectionElem::Deref)")
};assert!(matches!(place.projection[1], ProjectionElem::Deref));
61                *place =
62                    Place::from(self.replace_to).project_deeper(&[ProjectionElem::Deref], self.tcx);
63            }
64        }
65    }
66}
67
68fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> {
69    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:69",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(69u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?})",
                                                    instance) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?})", instance);
70
71    let mut result = match instance {
72        ty::InstanceKind::Item(..) => ::rustc_middle::util::bug::bug_fmt(format_args!("item {0:?} passed to make_shim",
        instance))bug!("item {:?} passed to make_shim", instance),
73        ty::InstanceKind::VTableShim(def_id) => {
74            let adjustment = Adjustment::Deref { source: DerefSource::MutPtr };
75            build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id))
76        }
77        ty::InstanceKind::FnPtrShim(def_id, ty) => {
78            let trait_ = tcx.parent(def_id);
79            // Supports `Fn` or `async Fn` traits.
80            let adjustment = match tcx
81                .fn_trait_kind_from_def_id(trait_)
82                .or_else(|| tcx.async_fn_trait_kind_from_def_id(trait_))
83            {
84                Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
85                Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef },
86                Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef },
87                None => ::rustc_middle::util::bug::bug_fmt(format_args!("fn pointer {0:?} is not an fn",
        ty))bug!("fn pointer {:?} is not an fn", ty),
88            };
89
90            build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty))
91        }
92        // We are generating a call back to our def-id, which the
93        // codegen backend knows to turn to an actual call, be it
94        // a virtual call, or a direct call to a function for which
95        // indirect calls must be codegen'd differently than direct ones
96        // (such as `#[track_caller]`).
97        ty::InstanceKind::ReifyShim(def_id, _) => {
98            build_call_shim(tcx, instance, None, CallKind::Direct(def_id))
99        }
100        ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => {
101            let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP);
102            let call_mut = tcx
103                .associated_items(fn_mut)
104                .in_definition_order()
105                .find(|it| it.is_fn())
106                .unwrap()
107                .def_id;
108
109            build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
110        }
111
112        ty::InstanceKind::ConstructCoroutineInClosureShim {
113            coroutine_closure_def_id,
114            receiver_by_ref,
115        } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref),
116
117        ty::InstanceKind::DropGlue(def_id, ty) => {
118            // FIXME(#91576): Drop shims for coroutines aren't subject to the MIR passes at the end
119            // of this function. Is this intentional?
120            if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) {
121                let coroutine_body = tcx.optimized_mir(coroutine_def_id);
122
123                let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
124                else {
125                    ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
126                };
127
128                // If this is a regular coroutine, grab its drop shim. If this is a coroutine
129                // that comes from a coroutine-closure, and the kind ty differs from the "maximum"
130                // kind that it supports, then grab the appropriate drop shim. This ensures that
131                // the future returned by `<[coroutine-closure] as AsyncFnOnce>::call_once` will
132                // drop the coroutine-closure's upvars.
133                let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
134                    coroutine_body.coroutine_drop().unwrap()
135                } else {
136                    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!(
137                        args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
138                        ty::ClosureKind::FnOnce
139                    );
140                    tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id))
141                        .coroutine_drop()
142                        .unwrap()
143                };
144
145                let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
146                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:146",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
                                                    instance, body) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", instance, body);
147
148                pm::run_passes(
149                    tcx,
150                    &mut body,
151                    &[
152                        &mentioned_items::MentionedItems,
153                        &abort_unwinding_calls::AbortUnwindingCalls,
154                        &add_call_guards::CriticalCallEdges,
155                    ],
156                    Some(MirPhase::Runtime(RuntimePhase::Optimized)),
157                    pm::Optimizations::Allowed,
158                );
159
160                return body;
161            }
162
163            build_drop_shim(tcx, def_id, ty)
164        }
165        ty::InstanceKind::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance),
166        ty::InstanceKind::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty),
167        ty::InstanceKind::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
168        ty::InstanceKind::FutureDropPollShim(def_id, proxy_ty, impl_ty) => {
169            let mut body =
170                async_destructor_ctor::build_future_drop_poll_shim(tcx, def_id, proxy_ty, impl_ty);
171
172            pm::run_passes(
173                tcx,
174                &mut body,
175                &[
176                    &mentioned_items::MentionedItems,
177                    &abort_unwinding_calls::AbortUnwindingCalls,
178                    &add_call_guards::CriticalCallEdges,
179                ],
180                Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
181                pm::Optimizations::Allowed,
182            );
183            run_optimization_passes(tcx, &mut body);
184            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:184",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(184u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
                                                    instance, body) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", instance, body);
185            return body;
186        }
187        ty::InstanceKind::AsyncDropGlue(def_id, ty) => {
188            let mut body = async_destructor_ctor::build_async_drop_shim(tcx, def_id, ty);
189
190            // Main pass required here is StateTransform to convert sync drop ladder
191            // into coroutine.
192            // Others are minimal passes as for sync drop glue shim
193            pm::run_passes(
194                tcx,
195                &mut body,
196                &[
197                    &mentioned_items::MentionedItems,
198                    &abort_unwinding_calls::AbortUnwindingCalls,
199                    &add_call_guards::CriticalCallEdges,
200                    &simplify::SimplifyCfg::MakeShim,
201                    &crate::coroutine::StateTransform,
202                ],
203                Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
204                pm::Optimizations::Allowed,
205            );
206            run_optimization_passes(tcx, &mut body);
207            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:207",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(207u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
                                                    instance, body) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", instance, body);
208            return body;
209        }
210
211        ty::InstanceKind::AsyncDropGlueCtorShim(def_id, ty) => {
212            let body = async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty);
213            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:213",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(213u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
                                                    instance, body) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", instance, body);
214            return body;
215        }
216        ty::InstanceKind::Virtual(..) => {
217            ::rustc_middle::util::bug::bug_fmt(format_args!("InstanceKind::Virtual ({0:?}) is for direct calls only",
        instance))bug!("InstanceKind::Virtual ({:?}) is for direct calls only", instance)
218        }
219        ty::InstanceKind::Intrinsic(_) => {
220            ::rustc_middle::util::bug::bug_fmt(format_args!("creating shims from intrinsics ({0:?}) is unsupported",
        instance))bug!("creating shims from intrinsics ({:?}) is unsupported", instance)
221        }
222    };
223    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:223",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(223u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = untransformed {1:?}",
                                                    instance, result) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = untransformed {:?}", instance, result);
224
225    deref_finder(tcx, &mut result, false);
226
227    // We don't validate MIR here because the shims may generate code that's
228    // only valid in a `PostAnalysis` param-env. However, since we do initial
229    // validation with the MirBuilt phase, which uses a user-facing param-env.
230    // This causes validation errors when TAITs are involved.
231    pm::run_passes_no_validate(
232        tcx,
233        &mut result,
234        &[
235            &mentioned_items::MentionedItems,
236            &add_moves_for_packed_drops::AddMovesForPackedDrops,
237            &remove_noop_landing_pads::RemoveNoopLandingPads,
238            &simplify::SimplifyCfg::MakeShim,
239            &instsimplify::InstSimplify::BeforeInline,
240            // Perform inlining of `#[rustc_force_inline]`-annotated callees.
241            &inline::ForceInline,
242            &abort_unwinding_calls::AbortUnwindingCalls,
243            &add_call_guards::CriticalCallEdges,
244        ],
245        Some(MirPhase::Runtime(RuntimePhase::Optimized)),
246    );
247
248    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:248",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(248u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
                                                    instance, result) as &dyn Value))])
            });
    } else { ; }
};debug!("make_shim({:?}) = {:?}", instance, result);
249
250    result
251}
252
253#[derive(#[automatically_derived]
impl ::core::marker::Copy for DerefSource { }Copy, #[automatically_derived]
impl ::core::clone::Clone for DerefSource {
    #[inline]
    fn clone(&self) -> DerefSource { *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::cmp::PartialEq for DerefSource {
    #[inline]
    fn eq(&self, other: &DerefSource) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
254enum DerefSource {
255    /// `fn shim(&self) { inner(*self )}`.
256    ImmRef,
257    /// `fn shim(&mut self) { inner(*self )}`.
258    MutRef,
259    /// `fn shim(*mut self) { inner(*self )}`.
260    MutPtr,
261}
262
263#[derive(#[automatically_derived]
impl ::core::marker::Copy for Adjustment { }Copy, #[automatically_derived]
impl ::core::clone::Clone for Adjustment {
    #[inline]
    fn clone(&self) -> Adjustment {
        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 {
            Adjustment::Identity =>
                ::core::fmt::Formatter::write_str(f, "Identity"),
            Adjustment::Deref { source: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f, "Deref",
                    "source", &__self_0),
            Adjustment::RefMut =>
                ::core::fmt::Formatter::write_str(f, "RefMut"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for Adjustment {
    #[inline]
    fn eq(&self, other: &Adjustment) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (Adjustment::Deref { source: __self_0 }, Adjustment::Deref {
                    source: __arg1_0 }) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq)]
264enum Adjustment {
265    /// Pass the receiver as-is.
266    Identity,
267
268    /// We get passed a reference or a raw pointer to `self` and call the target with `*self`.
269    ///
270    /// This either copies `self` (if `Self: Copy`, eg. for function items), or moves out of it
271    /// (for `VTableShim`, which effectively is passed `&own Self`).
272    Deref { source: DerefSource },
273
274    /// We get passed `self: Self` and call the target with `&mut self`.
275    ///
276    /// In this case we need to ensure that the `Self` is dropped after the call, as the callee
277    /// won't do it for us.
278    RefMut,
279}
280
281#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for CallKind<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for CallKind<'tcx> {
    #[inline]
    fn clone(&self) -> CallKind<'tcx> {
        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 {
            CallKind::Indirect(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "Indirect", &__self_0),
            CallKind::Direct(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Direct",
                    &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for CallKind<'tcx> {
    #[inline]
    fn eq(&self, other: &CallKind<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (CallKind::Indirect(__self_0), CallKind::Indirect(__arg1_0))
                    => __self_0 == __arg1_0,
                (CallKind::Direct(__self_0), CallKind::Direct(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq)]
282enum CallKind<'tcx> {
283    /// Call the `FnPtr` that was passed as the receiver.
284    Indirect(Ty<'tcx>),
285
286    /// Call a known `FnDef`.
287    Direct(DefId),
288}
289
290fn local_decls_for_sig<'tcx>(
291    sig: &ty::FnSig<'tcx>,
292    span: Span,
293) -> IndexVec<Local, LocalDecl<'tcx>> {
294    iter::once(LocalDecl::new(sig.output(), span))
295        .chain(sig.inputs().iter().map(|ity| LocalDecl::new(*ity, span).immutable()))
296        .collect()
297}
298
299fn dropee_emit_retag<'tcx>(
300    tcx: TyCtxt<'tcx>,
301    body: &mut Body<'tcx>,
302    mut dropee_ptr: Place<'tcx>,
303    span: Span,
304) -> Place<'tcx> {
305    if tcx.sess.opts.unstable_opts.mir_emit_retag {
306        let source_info = SourceInfo::outermost(span);
307        // We want to treat the function argument as if it was passed by `&mut`. As such, we
308        // generate
309        // ```
310        // temp = &mut *arg;
311        // Retag(temp, FnEntry)
312        // ```
313        // It's important that we do this first, before anything that depends on `dropee_ptr`
314        // has been put into the body.
315        let reborrow = Rvalue::Ref(
316            tcx.lifetimes.re_erased,
317            BorrowKind::Mut { kind: MutBorrowKind::Default },
318            tcx.mk_place_deref(dropee_ptr),
319        );
320        let ref_ty = reborrow.ty(body.local_decls(), tcx);
321        dropee_ptr = body.local_decls.push(LocalDecl::new(ref_ty, span)).into();
322        let new_statements = [
323            StatementKind::Assign(Box::new((dropee_ptr, reborrow))),
324            StatementKind::Retag(RetagKind::FnEntry, Box::new(dropee_ptr)),
325        ];
326        for s in new_statements {
327            body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, s));
328        }
329    }
330    dropee_ptr
331}
332
333fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>) -> Body<'tcx> {
334    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:334",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(334u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("build_drop_shim(def_id={0:?}, ty={1:?})",
                                                    def_id, ty) as &dyn Value))])
            });
    } else { ; }
};debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
335
336    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()));
337
338    let args = if let Some(ty) = ty {
339        tcx.mk_args(&[ty.into()])
340    } else {
341        GenericArgs::identity_for_item(tcx, def_id)
342    };
343    let sig = tcx.fn_sig(def_id).instantiate(tcx, args);
344    let sig = tcx.instantiate_bound_regions_with_erased(sig);
345    let span = tcx.def_span(def_id);
346
347    let source_info = SourceInfo::outermost(span);
348
349    let return_block = BasicBlock::new(1);
350    let mut blocks = IndexVec::with_capacity(2);
351    let block = |blocks: &mut IndexVec<_, _>, kind| {
352        blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false))
353    };
354    block(&mut blocks, TerminatorKind::Goto { target: return_block });
355    block(&mut blocks, TerminatorKind::Return);
356
357    let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty));
358    let mut body =
359        new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
360
361    // The first argument (index 0), but add 1 for the return value.
362    let dropee_ptr = Place::from(Local::new(1 + 0));
363    let dropee_ptr = dropee_emit_retag(tcx, &mut body, dropee_ptr, span);
364
365    if ty.is_some() {
366        let patch = {
367            let typing_env = ty::TypingEnv::post_analysis(tcx, def_id);
368            let mut elaborator = DropShimElaborator {
369                body: &body,
370                patch: MirPatch::new(&body),
371                tcx,
372                typing_env,
373                produce_async_drops: false,
374            };
375            let dropee = tcx.mk_place_deref(dropee_ptr);
376            let resume_block = elaborator.patch.resume_block();
377            elaborate_drop(
378                &mut elaborator,
379                source_info,
380                dropee,
381                (),
382                return_block,
383                Unwind::To(resume_block),
384                START_BLOCK,
385                None,
386            );
387            elaborator.patch
388        };
389        patch.apply(&mut body);
390    }
391
392    body
393}
394
395fn new_body<'tcx>(
396    source: MirSource<'tcx>,
397    basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
398    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
399    arg_count: usize,
400    span: Span,
401) -> Body<'tcx> {
402    let mut body = Body::new(
403        source,
404        basic_blocks,
405        IndexVec::from_elem_n(
406            SourceScopeData {
407                span,
408                parent_scope: None,
409                inlined: None,
410                inlined_parent_scope: None,
411                local_data: ClearCrossCrate::Clear,
412            },
413            1,
414        ),
415        local_decls,
416        IndexVec::new(),
417        arg_count,
418        ::alloc::vec::Vec::new()vec![],
419        span,
420        None,
421        // FIXME(compiler-errors): is this correct?
422        None,
423    );
424    // Shims do not directly mention any consts.
425    body.set_required_consts(Vec::new());
426    body
427}
428
429pub(super) struct DropShimElaborator<'a, 'tcx> {
430    pub body: &'a Body<'tcx>,
431    pub patch: MirPatch<'tcx>,
432    pub tcx: TyCtxt<'tcx>,
433    pub typing_env: ty::TypingEnv<'tcx>,
434    pub produce_async_drops: bool,
435}
436
437impl fmt::Debug for DropShimElaborator<'_, '_> {
438    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
439        f.debug_struct("DropShimElaborator").finish_non_exhaustive()
440    }
441}
442
443impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
444    type Path = ();
445
446    fn patch_ref(&self) -> &MirPatch<'tcx> {
447        &self.patch
448    }
449    fn patch(&mut self) -> &mut MirPatch<'tcx> {
450        &mut self.patch
451    }
452    fn body(&self) -> &'a Body<'tcx> {
453        self.body
454    }
455    fn tcx(&self) -> TyCtxt<'tcx> {
456        self.tcx
457    }
458    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
459        self.typing_env
460    }
461
462    fn terminator_loc(&self, bb: BasicBlock) -> Location {
463        self.patch.terminator_loc(self.body, bb)
464    }
465    fn allow_async_drops(&self) -> bool {
466        self.produce_async_drops
467    }
468
469    fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
470        match mode {
471            DropFlagMode::Shallow => {
472                // Drops for the contained fields are "shallow" and "static" - they will simply call
473                // the field's own drop glue.
474                DropStyle::Static
475            }
476            DropFlagMode::Deep => {
477                // The top-level drop is "deep" and "open" - it will be elaborated to a drop ladder
478                // dropping each field contained in the value.
479                DropStyle::Open
480            }
481        }
482    }
483
484    fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
485        None
486    }
487
488    fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {}
489
490    fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option<Self::Path> {
491        None
492    }
493    fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
494        None
495    }
496    fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
497        Some(())
498    }
499    fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
500        None
501    }
502}
503
504fn build_thread_local_shim<'tcx>(
505    tcx: TyCtxt<'tcx>,
506    instance: ty::InstanceKind<'tcx>,
507) -> Body<'tcx> {
508    let def_id = instance.def_id();
509
510    let span = tcx.def_span(def_id);
511    let source_info = SourceInfo::outermost(span);
512
513    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)))))])),
                    Some(Terminator {
                            source_info,
                            kind: TerminatorKind::Return,
                        }), false)]))vec![BasicBlockData::new_stmts(
514        vec![Statement::new(
515            source_info,
516            StatementKind::Assign(Box::new((
517                Place::return_place(),
518                Rvalue::ThreadLocalRef(def_id),
519            ))),
520        )],
521        Some(Terminator { source_info, kind: TerminatorKind::Return }),
522        false,
523    )]);
524
525    new_body(
526        MirSource::from_instance(instance),
527        blocks,
528        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)]),
529        0,
530        span,
531    )
532}
533
534/// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
535fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
536    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:536",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(536u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("build_clone_shim(def_id={0:?})",
                                                    def_id) as &dyn Value))])
            });
    } else { ; }
};debug!("build_clone_shim(def_id={:?})", def_id);
537
538    let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
539
540    let dest = Place::return_place();
541    let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
542
543    match self_ty.kind() {
544        ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
545        ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
546        ty::CoroutineClosure(_, args) => {
547            builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
548        }
549        ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
550        ty::Coroutine(coroutine_def_id, args) => {
551            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);
552            builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine())
553        }
554        _ => ::rustc_middle::util::bug::bug_fmt(format_args!("clone shim for `{0:?}` which is not `Copy` and is not an aggregate",
        self_ty))bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty),
555    };
556
557    builder.into_mir()
558}
559
560struct CloneShimBuilder<'tcx> {
561    tcx: TyCtxt<'tcx>,
562    def_id: DefId,
563    local_decls: IndexVec<Local, LocalDecl<'tcx>>,
564    blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
565    span: Span,
566    sig: ty::FnSig<'tcx>,
567}
568
569impl<'tcx> CloneShimBuilder<'tcx> {
570    fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
571        // we must instantiate the self_ty because it's
572        // otherwise going to be TySelf and we can't index
573        // or access fields of a Place of type TySelf.
574        let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]);
575        let sig = tcx.instantiate_bound_regions_with_erased(sig);
576        let span = tcx.def_span(def_id);
577
578        CloneShimBuilder {
579            tcx,
580            def_id,
581            local_decls: local_decls_for_sig(&sig, span),
582            blocks: IndexVec::new(),
583            span,
584            sig,
585        }
586    }
587
588    fn into_mir(self) -> Body<'tcx> {
589        let source = MirSource::from_instance(ty::InstanceKind::CloneShim(
590            self.def_id,
591            self.sig.inputs_and_output[0],
592        ));
593        new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
594    }
595
596    fn source_info(&self) -> SourceInfo {
597        SourceInfo::outermost(self.span)
598    }
599
600    fn block(
601        &mut self,
602        statements: Vec<Statement<'tcx>>,
603        kind: TerminatorKind<'tcx>,
604        is_cleanup: bool,
605    ) -> BasicBlock {
606        let source_info = self.source_info();
607        self.blocks.push(BasicBlockData::new_stmts(
608            statements,
609            Some(Terminator { source_info, kind }),
610            is_cleanup,
611        ))
612    }
613
614    /// Gives the index of an upcoming BasicBlock, with an offset.
615    /// offset=0 will give you the index of the next BasicBlock,
616    /// offset=1 will give the index of the next-to-next block,
617    /// offset=-1 will give you the index of the last-created block
618    fn block_index_offset(&self, offset: usize) -> BasicBlock {
619        BasicBlock::new(self.blocks.len() + offset)
620    }
621
622    fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
623        Statement::new(self.source_info(), kind)
624    }
625
626    fn copy_shim(&mut self) {
627        let rcvr = self.tcx.mk_place_deref(Place::from(Local::new(1 + 0)));
628        let ret_statement = self.make_statement(StatementKind::Assign(Box::new((
629            Place::return_place(),
630            Rvalue::Use(Operand::Copy(rcvr)),
631        ))));
632        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);
633    }
634
635    fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
636        let span = self.span;
637        let mut local = LocalDecl::new(ty, span);
638        if mutability.is_not() {
639            local = local.immutable();
640        }
641        Place::from(self.local_decls.push(local))
642    }
643
644    fn make_clone_call(
645        &mut self,
646        dest: Place<'tcx>,
647        src: Place<'tcx>,
648        ty: Ty<'tcx>,
649        next: BasicBlock,
650        cleanup: BasicBlock,
651    ) {
652        let tcx = self.tcx;
653
654        // `func == Clone::clone(&ty) -> ty`
655        let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]);
656        let func = Operand::Constant(Box::new(ConstOperand {
657            span: self.span,
658            user_ty: None,
659            const_: Const::zero_sized(func_ty),
660        }));
661
662        let ref_loc =
663            self.make_place(Mutability::Not, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty));
664
665        // `let ref_loc: &ty = &src;`
666        let statement = self.make_statement(StatementKind::Assign(Box::new((
667            ref_loc,
668            Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src),
669        ))));
670
671        // `let loc = Clone::clone(ref_loc);`
672        self.block(
673            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [statement]))vec![statement],
674            TerminatorKind::Call {
675                func,
676                args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
677                destination: dest,
678                target: Some(next),
679                unwind: UnwindAction::Cleanup(cleanup),
680                call_source: CallSource::Normal,
681                fn_span: self.span,
682            },
683            false,
684        );
685    }
686
687    fn clone_fields<I>(
688        &mut self,
689        dest: Place<'tcx>,
690        src: Place<'tcx>,
691        target: BasicBlock,
692        mut unwind: BasicBlock,
693        tys: I,
694    ) -> BasicBlock
695    where
696        I: IntoIterator<Item = Ty<'tcx>>,
697    {
698        // For an iterator of length n, create 2*n + 1 blocks.
699        for (i, ity) in tys.into_iter().enumerate() {
700            // Each iteration creates two blocks, referred to here as block 2*i and block 2*i + 1.
701            //
702            // Block 2*i attempts to clone the field. If successful it branches to 2*i + 2 (the
703            // next clone block). If unsuccessful it branches to the previous unwind block, which
704            // is initially the `unwind` argument passed to this function.
705            //
706            // Block 2*i + 1 is the unwind block for this iteration. It drops the cloned value
707            // created by block 2*i. We store this block in `unwind` so that the next clone block
708            // will unwind to it if cloning fails.
709
710            let field = FieldIdx::new(i);
711            let src_field = self.tcx.mk_place_field(src, field, ity);
712
713            let dest_field = self.tcx.mk_place_field(dest, field, ity);
714
715            let next_unwind = self.block_index_offset(1);
716            let next_block = self.block_index_offset(2);
717            self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
718            self.block(
719                ::alloc::vec::Vec::new()vec![],
720                TerminatorKind::Drop {
721                    place: dest_field,
722                    target: unwind,
723                    unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
724                    replace: false,
725                    drop: None,
726                    async_fut: None,
727                },
728                /* is_cleanup */ true,
729            );
730            unwind = next_unwind;
731        }
732        // If all clones succeed then we end up here.
733        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target }, false);
734        unwind
735    }
736
737    fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
738    where
739        I: IntoIterator<Item = Ty<'tcx>>,
740    {
741        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
742        let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
743        let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
744
745        let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
746    }
747
748    fn coroutine_shim(
749        &mut self,
750        dest: Place<'tcx>,
751        src: Place<'tcx>,
752        coroutine_def_id: DefId,
753        args: CoroutineArgs<TyCtxt<'tcx>>,
754    ) {
755        self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
756        let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
757        // This will get overwritten with a switch once we know the target blocks
758        let switch = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
759        let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
760        let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
761        let unreachable = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
762        let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count());
763        for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() {
764            let variant_index = VariantIdx::new(index);
765            let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
766            let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
767            let clone_block = self.block_index_offset(1);
768            let start_block = self.block(
769                ::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 {
770                    place: Box::new(Place::return_place()),
771                    variant_index,
772                })],
773                TerminatorKind::Goto { target: clone_block },
774                false,
775            );
776            cases.push((index as u128, start_block));
777            let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
778        }
779        let discr_ty = args.discr_ty(self.tcx);
780        let temp = self.make_place(Mutability::Mut, discr_ty);
781        let rvalue = Rvalue::Discriminant(src);
782        let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
783        match &mut self.blocks[switch] {
784            BasicBlockData { statements, terminator: Some(Terminator { kind, .. }), .. } => {
785                statements.push(statement);
786                *kind = TerminatorKind::SwitchInt {
787                    discr: Operand::Move(temp),
788                    targets: SwitchTargets::new(cases.into_iter(), unreachable),
789                };
790            }
791            BasicBlockData { terminator: None, .. } => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
792        }
793    }
794}
795
796/// Builds a "call" shim for `instance`. The shim calls the function specified by `call_kind`,
797/// first adjusting its first argument according to `rcvr_adjustment`.
798x;#[instrument(level = "debug", skip(tcx), ret)]
799fn build_call_shim<'tcx>(
800    tcx: TyCtxt<'tcx>,
801    instance: ty::InstanceKind<'tcx>,
802    rcvr_adjustment: Option<Adjustment>,
803    call_kind: CallKind<'tcx>,
804) -> Body<'tcx> {
805    // `FnPtrShim` contains the fn pointer type that a call shim is being built for - this is used
806    // to instantiate into the signature of the shim. It is not necessary for users of this
807    // MIR body to perform further instantiations (see `InstanceKind::has_polymorphic_mir_body`).
808    let (sig_args, untuple_args) = if let ty::InstanceKind::FnPtrShim(_, ty) = instance {
809        let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
810
811        let untuple_args = sig.inputs();
812
813        // Create substitutions for the `Self` and `Args` generic parameters of the shim body.
814        let arg_tup = Ty::new_tup(tcx, untuple_args);
815
816        (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
817    } else {
818        (None, None)
819    };
820
821    let def_id = instance.def_id();
822
823    let sig = tcx.fn_sig(def_id);
824    let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
825
826    assert_eq!(sig_args.is_some(), !instance.has_polymorphic_mir_body());
827    let mut sig = if let Some(sig_args) = sig_args {
828        sig.instantiate(tcx, &sig_args)
829    } else {
830        sig.instantiate_identity()
831    };
832
833    if let CallKind::Indirect(fnty) = call_kind {
834        // `sig` determines our local decls, and thus the callee type in the `Call` terminator. This
835        // can only be an `FnDef` or `FnPtr`, but currently will be `Self` since the types come from
836        // the implemented `FnX` trait.
837
838        // Apply the opposite adjustment to the MIR input.
839        let mut inputs_and_output = sig.inputs_and_output.to_vec();
840
841        // Initial signature is `fn(&? Self, Args) -> Self::Output` where `Args` is a tuple of the
842        // fn arguments. `Self` may be passed via (im)mutable reference or by-value.
843        assert_eq!(inputs_and_output.len(), 3);
844
845        // `Self` is always the original fn type `ty`. The MIR call terminator is only defined for
846        // `FnDef` and `FnPtr` callees, not the `Self` type param.
847        let self_arg = &mut inputs_and_output[0];
848        *self_arg = match rcvr_adjustment.unwrap() {
849            Adjustment::Identity => fnty,
850            Adjustment::Deref { source } => match source {
851                DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
852                DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
853                DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
854            },
855            Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {instance:?}"),
856        };
857        sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
858    }
859
860    // FIXME: Avoid having to adjust the signature both here and in
861    // `fn_sig_for_fn_abi`.
862    if let ty::InstanceKind::VTableShim(..) = instance {
863        // Modify fn(self, ...) to fn(self: *mut Self, ...)
864        let mut inputs_and_output = sig.inputs_and_output.to_vec();
865        let self_arg = &mut inputs_and_output[0];
866        debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
867        *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
868        sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
869    }
870
871    let span = tcx.def_span(def_id);
872
873    debug!(?sig);
874
875    let mut local_decls = local_decls_for_sig(&sig, span);
876    let source_info = SourceInfo::outermost(span);
877
878    let destination = Place::return_place();
879
880    let rcvr_place = || {
881        assert!(rcvr_adjustment.is_some());
882        Place::from(Local::new(1))
883    };
884    let mut statements = vec![];
885
886    let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
887        Adjustment::Identity => Operand::Move(rcvr_place()),
888        Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())),
889        Adjustment::RefMut => {
890            // let rcvr = &mut rcvr;
891            let ref_rcvr = local_decls.push(
892                LocalDecl::new(
893                    Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, sig.inputs()[0]),
894                    span,
895                )
896                .immutable(),
897            );
898            let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
899            statements.push(Statement::new(
900                source_info,
901                StatementKind::Assign(Box::new((
902                    Place::from(ref_rcvr),
903                    Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
904                ))),
905            ));
906            Operand::Move(Place::from(ref_rcvr))
907        }
908    });
909
910    let (callee, mut args) = match call_kind {
911        // `FnPtr` call has no receiver. Args are untupled below.
912        CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
913
914        // `FnDef` call with optional receiver.
915        CallKind::Direct(def_id) => {
916            let ty = tcx.type_of(def_id).instantiate_identity();
917            (
918                Operand::Constant(Box::new(ConstOperand {
919                    span,
920                    user_ty: None,
921                    const_: Const::zero_sized(ty),
922                })),
923                rcvr.into_iter().collect::<Vec<_>>(),
924            )
925        }
926    };
927
928    let mut arg_range = 0..sig.inputs().len();
929
930    // Take the `self` ("receiver") argument out of the range (it's adjusted above).
931    if rcvr_adjustment.is_some() {
932        arg_range.start += 1;
933    }
934
935    // Take the last argument, if we need to untuple it (handled below).
936    if untuple_args.is_some() {
937        arg_range.end -= 1;
938    }
939
940    // Pass all of the non-special arguments directly.
941    args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::new(1 + i)))));
942
943    // Untuple the last argument, if we have to.
944    if let Some(untuple_args) = untuple_args {
945        let tuple_arg = Local::new(1 + (sig.inputs().len() - 1));
946        args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
947            Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity))
948        }));
949    }
950
951    let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
952    let mut blocks = IndexVec::with_capacity(n_blocks);
953    let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
954        blocks.push(BasicBlockData::new_stmts(
955            statements,
956            Some(Terminator { source_info, kind }),
957            is_cleanup,
958        ))
959    };
960
961    // BB #0
962    let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
963    block(
964        &mut blocks,
965        statements,
966        TerminatorKind::Call {
967            func: callee,
968            args,
969            destination,
970            target: Some(BasicBlock::new(1)),
971            unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
972                UnwindAction::Cleanup(BasicBlock::new(3))
973            } else {
974                UnwindAction::Continue
975            },
976            call_source: CallSource::Misc,
977            fn_span: span,
978        },
979        false,
980    );
981
982    if let Some(Adjustment::RefMut) = rcvr_adjustment {
983        // BB #1 - drop for Self
984        block(
985            &mut blocks,
986            vec![],
987            TerminatorKind::Drop {
988                place: rcvr_place(),
989                target: BasicBlock::new(2),
990                unwind: UnwindAction::Continue,
991                replace: false,
992                drop: None,
993                async_fut: None,
994            },
995            false,
996        );
997    }
998    // BB #1/#2 - return
999    let stmts = vec![];
1000    block(&mut blocks, stmts, TerminatorKind::Return, false);
1001    if let Some(Adjustment::RefMut) = rcvr_adjustment {
1002        // BB #3 - drop if closure panics
1003        block(
1004            &mut blocks,
1005            vec![],
1006            TerminatorKind::Drop {
1007                place: rcvr_place(),
1008                target: BasicBlock::new(4),
1009                unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
1010                replace: false,
1011                drop: None,
1012                async_fut: None,
1013            },
1014            /* is_cleanup */ true,
1015        );
1016
1017        // BB #4 - resume
1018        block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
1019    }
1020
1021    let mut body =
1022        new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
1023
1024    if let ExternAbi::RustCall = sig.abi {
1025        body.spread_arg = Some(Local::new(sig.inputs().len()));
1026    }
1027
1028    body
1029}
1030
1031pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
1032    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));
1033
1034    let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
1035
1036    // Normalize the sig.
1037    let sig = tcx
1038        .fn_sig(ctor_id)
1039        .instantiate_identity()
1040        .no_bound_vars()
1041        .expect("LBR in ADT constructor signature");
1042    let sig = tcx.normalize_erasing_regions(typing_env, sig);
1043
1044    let ty::Adt(adt_def, args) = sig.output().kind() else {
1045        ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type for ADT ctor {0:?}",
        sig.output()));bug!("unexpected type for ADT ctor {:?}", sig.output());
1046    };
1047
1048    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:1048",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(1048u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("build_ctor: ctor_id={0:?} sig={1:?}",
                                                    ctor_id, sig) as &dyn Value))])
            });
    } else { ; }
};debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
1049
1050    let span = tcx.def_span(ctor_id);
1051
1052    let local_decls = local_decls_for_sig(&sig, span);
1053
1054    let source_info = SourceInfo::outermost(span);
1055
1056    let variant_index =
1057        if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
1058
1059    // Generate the following MIR:
1060    //
1061    // (return as Variant).field0 = arg0;
1062    // (return as Variant).field1 = arg1;
1063    //
1064    // return;
1065    {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:1065",
                        "rustc_mir_transform::shim", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_mir_transform/src/shim.rs"),
                        ::tracing_core::__macro_support::Option::Some(1065u32),
                        ::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};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&format_args!("build_ctor: variant_index={0:?}",
                                                    variant_index) as &dyn Value))])
            });
    } else { ; }
};debug!("build_ctor: variant_index={:?}", variant_index);
1066
1067    let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None);
1068    let variant = adt_def.variant(variant_index);
1069    let statement = Statement::new(
1070        source_info,
1071        StatementKind::Assign(Box::new((
1072            Place::return_place(),
1073            Rvalue::Aggregate(
1074                Box::new(kind),
1075                (0..variant.fields.len())
1076                    .map(|idx| Operand::Move(Place::from(Local::new(idx + 1))))
1077                    .collect(),
1078            ),
1079        ))),
1080    );
1081
1082    let start_block = BasicBlockData::new_stmts(
1083        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [statement]))vec![statement],
1084        Some(Terminator { source_info, kind: TerminatorKind::Return }),
1085        false,
1086    );
1087
1088    let source = MirSource::item(ctor_id);
1089    let mut body = new_body(
1090        source,
1091        IndexVec::from_elem_n(start_block, 1),
1092        local_decls,
1093        sig.inputs().len(),
1094        span,
1095    );
1096    // A constructor doesn't mention any other items (and we don't run the usual optimization passes
1097    // so this would otherwise not get filled).
1098    body.set_mentioned_items(Vec::new());
1099
1100    crate::pass_manager::dump_mir_for_phase_change(tcx, &body);
1101
1102    body
1103}
1104
1105/// ```ignore (pseudo-impl)
1106/// impl FnPtr for fn(u32) {
1107///     fn addr(self) -> usize {
1108///         self as usize
1109///     }
1110/// }
1111/// ```
1112fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
1113    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}");
1114    let span = tcx.def_span(def_id);
1115    let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars() else {
1116        ::rustc_middle::util::bug::span_bug_fmt(span,
    format_args!("FnPtr::addr with bound vars for `{0}`", self_ty));span_bug!(span, "FnPtr::addr with bound vars for `{self_ty}`");
1117    };
1118    let locals = local_decls_for_sig(&sig, span);
1119
1120    let source_info = SourceInfo::outermost(span);
1121    // FIXME: use `expose_provenance` once we figure out whether function pointers have meaningful
1122    // provenance.
1123    let rvalue = Rvalue::Cast(
1124        CastKind::FnPtrToPtr,
1125        Operand::Move(Place::from(Local::new(1))),
1126        Ty::new_imm_ptr(tcx, tcx.types.unit),
1127    );
1128    let stmt = Statement::new(
1129        source_info,
1130        StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1131    );
1132    let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [stmt]))vec![stmt];
1133    let start_block = BasicBlockData::new_stmts(
1134        statements,
1135        Some(Terminator { source_info, kind: TerminatorKind::Return }),
1136        false,
1137    );
1138    let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty));
1139    new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1140}
1141
1142fn build_construct_coroutine_by_move_shim<'tcx>(
1143    tcx: TyCtxt<'tcx>,
1144    coroutine_closure_def_id: DefId,
1145    receiver_by_ref: bool,
1146) -> Body<'tcx> {
1147    let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity();
1148    let mut self_local: Place<'tcx> = Local::from_usize(1).into();
1149    let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
1150        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1151    };
1152
1153    // We use `&Self` here because we only need to emit an ABI-compatible shim body,
1154    // rather than match the signature exactly (which might take `&mut self` instead).
1155    //
1156    // We adjust the `self_local` to be a deref since we want to copy fields out of
1157    // a reference to the closure.
1158    if receiver_by_ref {
1159        self_local = tcx.mk_place_deref(self_local);
1160        self_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, self_ty);
1161    }
1162
1163    let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
1164        tcx.mk_fn_sig(
1165            [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
1166            sig.to_coroutine_given_kind_and_upvars(
1167                tcx,
1168                args.as_coroutine_closure().parent_args(),
1169                tcx.coroutine_for_closure(coroutine_closure_def_id),
1170                ty::ClosureKind::FnOnce,
1171                tcx.lifetimes.re_erased,
1172                args.as_coroutine_closure().tupled_upvars_ty(),
1173                args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
1174            ),
1175            sig.c_variadic,
1176            sig.safety,
1177            sig.abi,
1178        )
1179    });
1180    let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
1181    let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else {
1182        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1183    };
1184
1185    let span = tcx.def_span(coroutine_closure_def_id);
1186    let locals = local_decls_for_sig(&sig, span);
1187
1188    let mut fields = ::alloc::vec::Vec::new()vec![];
1189
1190    // Move all of the closure args.
1191    for idx in 1..sig.inputs().len() {
1192        fields.push(Operand::Move(Local::from_usize(idx + 1).into()));
1193    }
1194
1195    for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
1196        if receiver_by_ref {
1197            // The only situation where it's possible is when we capture immuatable references,
1198            // since those don't need to be reborrowed with the closure's env lifetime. Since
1199            // references are always `Copy`, just emit a copy.
1200            if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Ref(_, _, hir::Mutability::Not) => true,
    _ => false,
}matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
1201                // This copy is only sound if it's a `&T`. This may be
1202                // reachable e.g. when eagerly computing the `Fn` instance
1203                // of an async closure that doesn't borrowck.
1204                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!(
1205                    "field should be captured by immutable ref if we have \
1206                    an `Fn` instance, but it was: {ty}"
1207                ));
1208            }
1209            fields.push(Operand::Copy(tcx.mk_place_field(
1210                self_local,
1211                FieldIdx::from_usize(idx),
1212                ty,
1213            )));
1214        } else {
1215            fields.push(Operand::Move(tcx.mk_place_field(
1216                self_local,
1217                FieldIdx::from_usize(idx),
1218                ty,
1219            )));
1220        }
1221    }
1222
1223    let source_info = SourceInfo::outermost(span);
1224    let rvalue = Rvalue::Aggregate(
1225        Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)),
1226        IndexVec::from_raw(fields),
1227    );
1228    let stmt = Statement::new(
1229        source_info,
1230        StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1231    );
1232    let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [stmt]))vec![stmt];
1233    let start_block = BasicBlockData::new_stmts(
1234        statements,
1235        Some(Terminator { source_info, kind: TerminatorKind::Return }),
1236        false,
1237    );
1238
1239    let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim {
1240        coroutine_closure_def_id,
1241        receiver_by_ref,
1242    });
1243
1244    let body =
1245        new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
1246
1247    let pass_name =
1248        if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" };
1249    if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) {
1250        dumper.dump_mir(&body);
1251    }
1252
1253    body
1254}