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, Unnormalized,
13};
14use rustc_middle::{bug, span_bug};
15use rustc_span::{DUMMY_SP, Span, Spanned, dummy_spanned};
16use tracing::{debug, instrument};
17
18use crate::deref_separator::deref_finder;
19use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
20use crate::patch::MirPatch;
21use crate::{
22 abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, inline, instsimplify,
23 mentioned_items, pass_manager as pm, remove_noop_landing_pads, run_optimization_passes,
24 simplify,
25};
26
27mod async_destructor_ctor;
28
29pub(super) fn provide(providers: &mut Providers) {
30 providers.mir_shims = make_shim;
31}
32
33struct FixProxyFutureDropVisitor<'tcx> {
35 tcx: TyCtxt<'tcx>,
36 replace_to: Local,
37}
38
39impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> {
40 fn tcx(&self) -> TyCtxt<'tcx> {
41 self.tcx
42 }
43
44 fn visit_place(
45 &mut self,
46 place: &mut Place<'tcx>,
47 _context: PlaceContext,
48 _location: Location,
49 ) {
50 if place.local == Local::from_u32(1) {
51 if place.projection.len() == 1 {
52 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!(
53 place.projection.first(),
54 Some(ProjectionElem::Field(FieldIdx::ZERO, _))
55 ));
56 *place = Place::from(self.replace_to);
57 } else if place.projection.len() == 2 {
58 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, _)));
59 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));
60 *place =
61 Place::from(self.replace_to).project_deeper(&[ProjectionElem::Deref], self.tcx);
62 }
63 }
64 }
65}
66
67fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<'tcx> {
68 {
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:68",
"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(68u32),
::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);
69
70 let mut result = match instance {
71 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),
72 ty::InstanceKind::VTableShim(def_id) => {
73 let adjustment = Adjustment::Deref { source: DerefSource::MutPtr };
74 build_call_shim(tcx, instance, Some(adjustment), CallKind::Direct(def_id))
75 }
76 ty::InstanceKind::FnPtrShim(def_id, ty) => {
77 let trait_ = tcx.parent(def_id);
78 let adjustment = match tcx
80 .fn_trait_kind_from_def_id(trait_)
81 .or_else(|| tcx.async_fn_trait_kind_from_def_id(trait_))
82 {
83 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
84 Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef },
85 Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef },
86 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),
87 };
88
89 build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect(ty))
90 }
91 ty::InstanceKind::ReifyShim(def_id, _) => {
97 build_call_shim(tcx, instance, None, CallKind::Direct(def_id))
98 }
99 ty::InstanceKind::ClosureOnceShim { call_once: _, track_caller: _ } => {
100 let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP);
101 let call_mut = tcx
102 .associated_items(fn_mut)
103 .in_definition_order()
104 .find(|it| it.is_fn())
105 .unwrap()
106 .def_id;
107
108 build_call_shim(tcx, instance, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
109 }
110
111 ty::InstanceKind::ConstructCoroutineInClosureShim {
112 coroutine_closure_def_id,
113 receiver_by_ref,
114 } => build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref),
115
116 ty::InstanceKind::DropGlue(def_id, ty) => {
117 if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) {
120 let coroutine_body = tcx.optimized_mir(coroutine_def_id);
121
122 let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
123 else {
124 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
125 };
126
127 let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
133 coroutine_body.coroutine_drop().unwrap()
134 } else {
135 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!(
136 args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
137 ty::ClosureKind::FnOnce
138 );
139 tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id))
140 .coroutine_drop()
141 .unwrap()
142 };
143
144 let mut body =
145 EarlyBinder::bind(body.clone()).instantiate(tcx, args).skip_norm_wip();
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, ty::TypingEnv::post_analysis(tcx, def_id))
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 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 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 &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 ImmRef,
257 MutRef,
259 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 Identity,
267
268 Deref { source: DerefSource },
273
274 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 Indirect(Ty<'tcx>),
285
286 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
299pub fn build_drop_shim<'tcx>(
304 tcx: TyCtxt<'tcx>,
305 def_id: DefId,
306 ty: Option<Ty<'tcx>>,
307 typing_env: ty::TypingEnv<'tcx>,
308) -> Body<'tcx> {
309 {
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:309",
"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(309u32),
::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);
310
311 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()));
312
313 let args = if let Some(ty) = ty {
314 tcx.mk_args(&[ty.into()])
315 } else {
316 GenericArgs::identity_for_item(tcx, def_id)
317 };
318 let sig = tcx.fn_sig(def_id).instantiate(tcx, args).skip_norm_wip();
319 let sig = tcx.instantiate_bound_regions_with_erased(sig);
320 let span = tcx.def_span(def_id);
321
322 let source_info = SourceInfo::outermost(span);
323
324 let return_block = BasicBlock::new(1);
325 let mut blocks = IndexVec::with_capacity(2);
326 let block = |blocks: &mut IndexVec<_, _>, kind| {
327 blocks.push(BasicBlockData::new(Some(Terminator { source_info, kind }), false))
328 };
329 if ty.is_some() {
330 block(&mut blocks, TerminatorKind::Goto { target: return_block });
331 }
332 block(&mut blocks, TerminatorKind::Return);
333
334 let source = MirSource::from_instance(ty::InstanceKind::DropGlue(def_id, ty));
335 let mut body =
336 new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
337
338 let Some(ty) = ty else {
339 return body;
340 };
341
342 let dropee_ptr = Place::from(Local::arg(0));
343
344 if let ty::Array(ety, _len) = *ty.kind() {
345 let slice_ty = Ty::new_slice(tcx, ety);
348 let mut_slice_ty = Ty::new_ref(tcx, tcx.lifetimes.re_erased, slice_ty, ty::Mutability::Mut);
349 let erased_local = body.local_decls.push(LocalDecl::new(mut_slice_ty, span));
350
351 let start = &mut body.basic_blocks_mut()[START_BLOCK];
352 start.statements.push(Statement::new(
353 source_info,
354 StatementKind::Assign(Box::new((
355 Place::from(erased_local),
356 Rvalue::Cast(
357 CastKind::PointerCoercion(
358 ty::adjustment::PointerCoercion::Unsize,
359 CoercionSource::Implicit,
360 ),
361 Operand::Move(dropee_ptr),
362 mut_slice_ty,
363 ),
364 ))),
365 ));
366 start.terminator = Some(Terminator {
367 source_info,
368 kind: TerminatorKind::Call {
369 func: Operand::function_handle(tcx, def_id, [ty::GenericArg::from(slice_ty)], span),
370 args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]),
371 destination: Place::from(RETURN_PLACE),
372 target: Some(return_block),
373 unwind: UnwindAction::Continue,
374 call_source: CallSource::Misc,
375 fn_span: span,
376 },
377 });
378 } else {
379 let patch = {
380 let mut elaborator = DropShimElaborator {
381 body: &body,
382 patch: MirPatch::new(&body),
383 tcx,
384 typing_env,
385 produce_async_drops: false,
386 };
387 let dropee = tcx.mk_place_deref(dropee_ptr);
388 let resume_block = elaborator.patch.resume_block();
389 elaborate_drop(
390 &mut elaborator,
391 source_info,
392 dropee,
393 (),
394 return_block,
395 Unwind::To(resume_block),
396 START_BLOCK,
397 None,
398 );
399 elaborator.patch
400 };
401 patch.apply(&mut body);
402 }
403
404 body
405}
406
407fn new_body<'tcx>(
408 source: MirSource<'tcx>,
409 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
410 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
411 arg_count: usize,
412 span: Span,
413) -> Body<'tcx> {
414 let mut body = Body::new(
415 source,
416 basic_blocks,
417 IndexVec::from_elem_n(
418 SourceScopeData {
419 span,
420 parent_scope: None,
421 inlined: None,
422 inlined_parent_scope: None,
423 local_data: ClearCrossCrate::Clear,
424 },
425 1,
426 ),
427 local_decls,
428 IndexVec::new(),
429 arg_count,
430 ::alloc::vec::Vec::new()vec![],
431 span,
432 None,
433 None,
435 );
436 body.set_required_consts(Vec::new());
438 body
439}
440
441pub(super) struct DropShimElaborator<'a, 'tcx> {
442 pub body: &'a Body<'tcx>,
443 pub patch: MirPatch<'tcx>,
444 pub tcx: TyCtxt<'tcx>,
445 pub typing_env: ty::TypingEnv<'tcx>,
446 pub produce_async_drops: bool,
447}
448
449impl fmt::Debug for DropShimElaborator<'_, '_> {
450 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
451 f.debug_struct("DropShimElaborator").finish_non_exhaustive()
452 }
453}
454
455impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
456 type Path = ();
457
458 fn patch_ref(&self) -> &MirPatch<'tcx> {
459 &self.patch
460 }
461 fn patch(&mut self) -> &mut MirPatch<'tcx> {
462 &mut self.patch
463 }
464 fn body(&self) -> &'a Body<'tcx> {
465 self.body
466 }
467 fn tcx(&self) -> TyCtxt<'tcx> {
468 self.tcx
469 }
470 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
471 self.typing_env
472 }
473
474 fn terminator_loc(&self, bb: BasicBlock) -> Location {
475 self.patch.terminator_loc(self.body, bb)
476 }
477 fn allow_async_drops(&self) -> bool {
478 self.produce_async_drops
479 }
480
481 fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
482 match mode {
483 DropFlagMode::Shallow => {
484 DropStyle::Static
487 }
488 DropFlagMode::Deep => {
489 DropStyle::Open
492 }
493 }
494 }
495
496 fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
497 None
498 }
499
500 fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {}
501
502 fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option<Self::Path> {
503 None
504 }
505 fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
506 None
507 }
508 fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
509 Some(())
510 }
511 fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
512 None
513 }
514}
515
516fn build_thread_local_shim<'tcx>(
517 tcx: TyCtxt<'tcx>,
518 instance: ty::InstanceKind<'tcx>,
519) -> Body<'tcx> {
520 let def_id = instance.def_id();
521
522 let span = tcx.def_span(def_id);
523 let source_info = SourceInfo::outermost(span);
524
525 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(
526 vec![Statement::new(
527 source_info,
528 StatementKind::Assign(Box::new((
529 Place::return_place(),
530 Rvalue::ThreadLocalRef(def_id),
531 ))),
532 )],
533 Some(Terminator { source_info, kind: TerminatorKind::Return }),
534 false,
535 )]);
536
537 new_body(
538 MirSource::from_instance(instance),
539 blocks,
540 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)]),
541 0,
542 span,
543 )
544}
545
546fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
548 {
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:548",
"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(548u32),
::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);
549
550 let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
551
552 let dest = Place::return_place();
553 let src = tcx.mk_place_deref(Place::from(Local::arg(0)));
554
555 match self_ty.kind() {
556 ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
557 ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
558 ty::CoroutineClosure(_, args) => {
559 builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
560 }
561 ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
562 ty::Coroutine(coroutine_def_id, args) => {
563 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);
564 builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine())
565 }
566 _ => ::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),
567 };
568
569 builder.into_mir()
570}
571
572struct CloneShimBuilder<'tcx> {
573 tcx: TyCtxt<'tcx>,
574 def_id: DefId,
575 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
576 blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
577 span: Span,
578 sig: ty::FnSig<'tcx>,
579}
580
581impl<'tcx> CloneShimBuilder<'tcx> {
582 fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
583 let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip();
587 let sig = tcx.instantiate_bound_regions_with_erased(sig);
588 let span = tcx.def_span(def_id);
589
590 CloneShimBuilder {
591 tcx,
592 def_id,
593 local_decls: local_decls_for_sig(&sig, span),
594 blocks: IndexVec::new(),
595 span,
596 sig,
597 }
598 }
599
600 fn into_mir(self) -> Body<'tcx> {
601 let source = MirSource::from_instance(ty::InstanceKind::CloneShim(
602 self.def_id,
603 self.sig.inputs_and_output[0],
604 ));
605 new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
606 }
607
608 fn source_info(&self) -> SourceInfo {
609 SourceInfo::outermost(self.span)
610 }
611
612 fn block(
613 &mut self,
614 statements: Vec<Statement<'tcx>>,
615 kind: TerminatorKind<'tcx>,
616 is_cleanup: bool,
617 ) -> BasicBlock {
618 let source_info = self.source_info();
619 self.blocks.push(BasicBlockData::new_stmts(
620 statements,
621 Some(Terminator { source_info, kind }),
622 is_cleanup,
623 ))
624 }
625
626 fn block_index_offset(&self, offset: usize) -> BasicBlock {
631 BasicBlock::new(self.blocks.len() + offset)
632 }
633
634 fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
635 Statement::new(self.source_info(), kind)
636 }
637
638 fn copy_shim(&mut self) {
639 let rcvr = self.tcx.mk_place_deref(Place::from(Local::arg(0)));
640 let ret_statement = self.make_statement(StatementKind::Assign(Box::new((
641 Place::return_place(),
642 Rvalue::Use(Operand::Copy(rcvr), WithRetag::Yes),
643 ))));
644 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);
645 }
646
647 fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
648 let span = self.span;
649 let mut local = LocalDecl::new(ty, span);
650 if mutability.is_not() {
651 local = local.immutable();
652 }
653 Place::from(self.local_decls.push(local))
654 }
655
656 fn make_clone_call(
657 &mut self,
658 dest: Place<'tcx>,
659 src: Place<'tcx>,
660 ty: Ty<'tcx>,
661 next: BasicBlock,
662 cleanup: BasicBlock,
663 ) {
664 let tcx = self.tcx;
665
666 let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]);
668 let func = Operand::Constant(Box::new(ConstOperand {
669 span: self.span,
670 user_ty: None,
671 const_: Const::zero_sized(func_ty),
672 }));
673
674 let ref_loc =
675 self.make_place(Mutability::Not, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty));
676
677 let statement = self.make_statement(StatementKind::Assign(Box::new((
679 ref_loc,
680 Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src),
681 ))));
682
683 self.block(
685 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
686 TerminatorKind::Call {
687 func,
688 args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
689 destination: dest,
690 target: Some(next),
691 unwind: UnwindAction::Cleanup(cleanup),
692 call_source: CallSource::Normal,
693 fn_span: self.span,
694 },
695 false,
696 );
697 }
698
699 fn clone_fields<I>(
700 &mut self,
701 dest: Place<'tcx>,
702 src: Place<'tcx>,
703 target: BasicBlock,
704 mut unwind: BasicBlock,
705 tys: I,
706 ) -> BasicBlock
707 where
708 I: IntoIterator<Item = Ty<'tcx>>,
709 {
710 for (i, ity) in tys.into_iter().enumerate() {
712 let field = FieldIdx::new(i);
723 let src_field = self.tcx.mk_place_field(src, field, ity);
724
725 let dest_field = self.tcx.mk_place_field(dest, field, ity);
726
727 let next_unwind = self.block_index_offset(1);
728 let next_block = self.block_index_offset(2);
729 self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
730 self.block(
731 ::alloc::vec::Vec::new()vec![],
732 TerminatorKind::Drop {
733 place: dest_field,
734 target: unwind,
735 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
736 replace: false,
737 drop: None,
738 async_fut: None,
739 },
740 true,
741 );
742 unwind = next_unwind;
743 }
744 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target }, false);
746 unwind
747 }
748
749 fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
750 where
751 I: IntoIterator<Item = Ty<'tcx>>,
752 {
753 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
754 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
755 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
756
757 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
758 }
759
760 fn coroutine_shim(
761 &mut self,
762 dest: Place<'tcx>,
763 src: Place<'tcx>,
764 coroutine_def_id: DefId,
765 args: CoroutineArgs<TyCtxt<'tcx>>,
766 ) {
767 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
768 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
769 let switch = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
771 let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
772 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
773 let unreachable = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
774 let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count());
775 for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() {
776 let variant_index = VariantIdx::new(index);
777 let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
778 let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
779 let clone_block = self.block_index_offset(1);
780 let start_block = self.block(
781 ::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 {
782 place: Box::new(Place::return_place()),
783 variant_index,
784 })],
785 TerminatorKind::Goto { target: clone_block },
786 false,
787 );
788 cases.push((index as u128, start_block));
789 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
790 }
791 let discr_ty = args.discr_ty(self.tcx);
792 let temp = self.make_place(Mutability::Mut, discr_ty);
793 let rvalue = Rvalue::Discriminant(src);
794 let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
795 match &mut self.blocks[switch] {
796 BasicBlockData { statements, terminator: Some(Terminator { kind, .. }), .. } => {
797 statements.push(statement);
798 *kind = TerminatorKind::SwitchInt {
799 discr: Operand::Move(temp),
800 targets: SwitchTargets::new(cases.into_iter(), unreachable),
801 };
802 }
803 BasicBlockData { terminator: None, .. } => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
804 }
805 }
806}
807
808x;#[instrument(level = "debug", skip(tcx), ret)]
811fn build_call_shim<'tcx>(
812 tcx: TyCtxt<'tcx>,
813 instance: ty::InstanceKind<'tcx>,
814 rcvr_adjustment: Option<Adjustment>,
815 call_kind: CallKind<'tcx>,
816) -> Body<'tcx> {
817 let (sig_args, untuple_args) = if let ty::InstanceKind::FnPtrShim(_, ty) = instance {
821 let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
822
823 let untuple_args = sig.inputs();
824
825 let arg_tup = Ty::new_tup(tcx, untuple_args);
827
828 (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
829 } else {
830 (None, None)
831 };
832
833 let def_id = instance.def_id();
834
835 let sig = tcx.fn_sig(def_id);
836 let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
837
838 assert_eq!(sig_args.is_some(), !instance.has_polymorphic_mir_body());
839 let mut sig = if let Some(sig_args) = sig_args {
840 sig.instantiate(tcx, &sig_args).skip_norm_wip()
841 } else {
842 sig.instantiate_identity().skip_norm_wip()
843 };
844
845 if let CallKind::Indirect(fnty) = call_kind {
846 let mut inputs_and_output = sig.inputs_and_output.to_vec();
852
853 assert_eq!(inputs_and_output.len(), 3);
856
857 let self_arg = &mut inputs_and_output[0];
860 *self_arg = match rcvr_adjustment.unwrap() {
861 Adjustment::Identity => fnty,
862 Adjustment::Deref { source } => match source {
863 DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
864 DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
865 DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
866 },
867 Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {instance:?}"),
868 };
869 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
870 }
871
872 if let ty::InstanceKind::VTableShim(..) = instance {
875 let mut inputs_and_output = sig.inputs_and_output.to_vec();
877 let self_arg = &mut inputs_and_output[0];
878 debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
879 *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
880 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
881 }
882
883 let span = tcx.def_span(def_id);
884
885 debug!(?sig);
886
887 let mut local_decls = local_decls_for_sig(&sig, span);
888 let source_info = SourceInfo::outermost(span);
889
890 let destination = Place::return_place();
891
892 let rcvr_place = || {
893 assert!(rcvr_adjustment.is_some());
894 Place::from(Local::arg(0))
895 };
896 let mut statements = vec![];
897
898 let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
899 Adjustment::Identity => Operand::Move(rcvr_place()),
900 Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())),
901 Adjustment::RefMut => {
902 let ref_rcvr = local_decls.push(
904 LocalDecl::new(
905 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, sig.inputs()[0]),
906 span,
907 )
908 .immutable(),
909 );
910 let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
911 statements.push(Statement::new(
912 source_info,
913 StatementKind::Assign(Box::new((
914 Place::from(ref_rcvr),
915 Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
916 ))),
917 ));
918 Operand::Move(Place::from(ref_rcvr))
919 }
920 });
921
922 let (callee, mut args) = match call_kind {
923 CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
925
926 CallKind::Direct(def_id) => {
928 let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
929 (
930 Operand::Constant(Box::new(ConstOperand {
931 span,
932 user_ty: None,
933 const_: Const::zero_sized(ty),
934 })),
935 rcvr.into_iter().collect::<Vec<_>>(),
936 )
937 }
938 };
939
940 let mut arg_range = 0..sig.inputs().len();
941
942 if rcvr_adjustment.is_some() {
944 arg_range.start += 1;
945 }
946
947 if untuple_args.is_some() {
949 arg_range.end -= 1;
950 }
951
952 args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::arg(i)))));
954
955 if let Some(untuple_args) = untuple_args {
957 let tuple_arg = Local::arg(sig.inputs().len() - 1);
958 args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
959 Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity))
960 }));
961 }
962
963 let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
964 let mut blocks = IndexVec::with_capacity(n_blocks);
965 let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
966 blocks.push(BasicBlockData::new_stmts(
967 statements,
968 Some(Terminator { source_info, kind }),
969 is_cleanup,
970 ))
971 };
972
973 let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
975 block(
976 &mut blocks,
977 statements,
978 TerminatorKind::Call {
979 func: callee,
980 args,
981 destination,
982 target: Some(BasicBlock::new(1)),
983 unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
984 UnwindAction::Cleanup(BasicBlock::new(3))
985 } else {
986 UnwindAction::Continue
987 },
988 call_source: CallSource::Misc,
989 fn_span: span,
990 },
991 false,
992 );
993
994 if let Some(Adjustment::RefMut) = rcvr_adjustment {
995 block(
997 &mut blocks,
998 vec![],
999 TerminatorKind::Drop {
1000 place: rcvr_place(),
1001 target: BasicBlock::new(2),
1002 unwind: UnwindAction::Continue,
1003 replace: false,
1004 drop: None,
1005 async_fut: None,
1006 },
1007 false,
1008 );
1009 }
1010 let stmts = vec![];
1012 block(&mut blocks, stmts, TerminatorKind::Return, false);
1013 if let Some(Adjustment::RefMut) = rcvr_adjustment {
1014 block(
1016 &mut blocks,
1017 vec![],
1018 TerminatorKind::Drop {
1019 place: rcvr_place(),
1020 target: BasicBlock::new(4),
1021 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
1022 replace: false,
1023 drop: None,
1024 async_fut: None,
1025 },
1026 true,
1027 );
1028
1029 block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
1031 }
1032
1033 let mut body =
1034 new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
1035
1036 if let ExternAbi::RustCall = sig.abi() {
1037 body.spread_arg = Some(Local::new(sig.inputs().len()));
1038 }
1039
1040 body
1041}
1042
1043pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
1044 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));
1045
1046 let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
1047
1048 let sig = tcx
1050 .fn_sig(ctor_id)
1051 .instantiate_identity()
1052 .skip_norm_wip()
1053 .no_bound_vars()
1054 .expect("LBR in ADT constructor signature");
1055 let sig = tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(sig));
1056
1057 let ty::Adt(adt_def, args) = sig.output().kind() else {
1058 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type for ADT ctor {0:?}",
sig.output()));bug!("unexpected type for ADT ctor {:?}", sig.output());
1059 };
1060
1061 {
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:1061",
"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(1061u32),
::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);
1062
1063 let span = tcx.def_span(ctor_id);
1064
1065 let local_decls = local_decls_for_sig(&sig, span);
1066
1067 let source_info = SourceInfo::outermost(span);
1068
1069 let variant_index =
1070 if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
1071
1072 {
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:1078",
"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(1078u32),
::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);
1079
1080 let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None);
1081 let variant = adt_def.variant(variant_index);
1082 let statement = Statement::new(
1083 source_info,
1084 StatementKind::Assign(Box::new((
1085 Place::return_place(),
1086 Rvalue::Aggregate(
1087 Box::new(kind),
1088 (0..variant.fields.len())
1089 .map(|idx| Operand::Move(Place::from(Local::arg(idx))))
1090 .collect(),
1091 ),
1092 ))),
1093 );
1094
1095 let start_block = BasicBlockData::new_stmts(
1096 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
1097 Some(Terminator { source_info, kind: TerminatorKind::Return }),
1098 false,
1099 );
1100
1101 let source = MirSource::item(ctor_id);
1102 let mut body = new_body(
1103 source,
1104 IndexVec::from_elem_n(start_block, 1),
1105 local_decls,
1106 sig.inputs().len(),
1107 span,
1108 );
1109 body.set_mentioned_items(Vec::new());
1112
1113 crate::pass_manager::dump_mir_for_phase_change(tcx, &body);
1114
1115 body
1116}
1117
1118fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
1126 {
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}");
1127 let span = tcx.def_span(def_id);
1128 let Some(sig) =
1129 tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip().no_bound_vars()
1130 else {
1131 ::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}`");
1132 };
1133 let locals = local_decls_for_sig(&sig, span);
1134
1135 let source_info = SourceInfo::outermost(span);
1136 let rvalue = Rvalue::Cast(
1139 CastKind::FnPtrToPtr,
1140 Operand::Move(Place::from(Local::arg(0))),
1141 Ty::new_imm_ptr(tcx, tcx.types.unit),
1142 );
1143 let stmt = Statement::new(
1144 source_info,
1145 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1146 );
1147 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1148 let start_block = BasicBlockData::new_stmts(
1149 statements,
1150 Some(Terminator { source_info, kind: TerminatorKind::Return }),
1151 false,
1152 );
1153 let source = MirSource::from_instance(ty::InstanceKind::FnPtrAddrShim(def_id, self_ty));
1154 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1155}
1156
1157fn build_construct_coroutine_by_move_shim<'tcx>(
1158 tcx: TyCtxt<'tcx>,
1159 coroutine_closure_def_id: DefId,
1160 receiver_by_ref: bool,
1161) -> Body<'tcx> {
1162 let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity().skip_norm_wip();
1163 let mut self_local: Place<'tcx> = Local::arg(0).into();
1164 let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
1165 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1166 };
1167
1168 if receiver_by_ref {
1174 self_local = tcx.mk_place_deref(self_local);
1175 self_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, self_ty);
1176 }
1177
1178 let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
1179 tcx.mk_fn_sig(
1180 [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
1181 sig.to_coroutine_given_kind_and_upvars(
1182 tcx,
1183 args.as_coroutine_closure().parent_args(),
1184 tcx.coroutine_for_closure(coroutine_closure_def_id),
1185 ty::ClosureKind::FnOnce,
1186 tcx.lifetimes.re_erased,
1187 args.as_coroutine_closure().tupled_upvars_ty(),
1188 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
1189 ),
1190 sig.fn_sig_kind,
1191 )
1192 });
1193 let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
1194 let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else {
1195 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1196 };
1197
1198 let span = tcx.def_span(coroutine_closure_def_id);
1199 let locals = local_decls_for_sig(&sig, span);
1200
1201 let mut fields = ::alloc::vec::Vec::new()vec![];
1202
1203 for idx in 1..sig.inputs().len() {
1205 fields.push(Operand::Move(Local::arg(idx).into()));
1206 }
1207
1208 for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
1209 if receiver_by_ref {
1210 if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Ref(_, _, hir::Mutability::Not) => true,
_ => false,
}matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
1214 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!(
1218 "field should be captured by immutable ref if we have \
1219 an `Fn` instance, but it was: {ty}"
1220 ));
1221 }
1222 fields.push(Operand::Copy(tcx.mk_place_field(
1223 self_local,
1224 FieldIdx::from_usize(idx),
1225 ty,
1226 )));
1227 } else {
1228 fields.push(Operand::Move(tcx.mk_place_field(
1229 self_local,
1230 FieldIdx::from_usize(idx),
1231 ty,
1232 )));
1233 }
1234 }
1235
1236 let source_info = SourceInfo::outermost(span);
1237 let rvalue = Rvalue::Aggregate(
1238 Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)),
1239 IndexVec::from_raw(fields),
1240 );
1241 let stmt = Statement::new(
1242 source_info,
1243 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1244 );
1245 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1246 let start_block = BasicBlockData::new_stmts(
1247 statements,
1248 Some(Terminator { source_info, kind: TerminatorKind::Return }),
1249 false,
1250 );
1251
1252 let source = MirSource::from_instance(ty::InstanceKind::ConstructCoroutineInClosureShim {
1253 coroutine_closure_def_id,
1254 receiver_by_ref,
1255 });
1256
1257 let body =
1258 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
1259
1260 let pass_name =
1261 if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" };
1262 if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) {
1263 dumper.dump_mir(&body);
1264 }
1265
1266 body
1267}