1use std::{assert_matches, fmt, iter};
2
3use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx};
4use rustc_data_structures::thin_vec::ThinVec;
5use rustc_hir as hir;
6use rustc_hir::def_id::DefId;
7use rustc_hir::lang_items::LangItem;
8use rustc_index::{Idx, IndexVec};
9use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
10use rustc_middle::mir::*;
11use rustc_middle::query::Providers;
12use rustc_middle::ty::{
13 self, CoroutineArgs, CoroutineArgsExt, EarlyBinder, GenericArgs, Ty, TyCtxt, Unnormalized,
14};
15use rustc_middle::{bug, span_bug};
16use rustc_span::{DUMMY_SP, Span, Spanned, dummy_spanned};
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
34fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> {
35 {
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:35",
"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(35u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?})",
shim) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?})", shim);
36
37 let mut result = match shim {
38 ty::ShimKind::VTable(def_id) => {
39 let adjustment = Adjustment::Deref { source: DerefSource::MutPtr };
40 build_call_shim(tcx, shim, Some(adjustment), CallKind::Direct(def_id))
41 }
42 ty::ShimKind::FnPtr(def_id, ty) => {
43 let trait_ = tcx.parent(def_id);
44 let adjustment = match tcx
46 .fn_trait_kind_from_def_id(trait_)
47 .or_else(|| tcx.async_fn_trait_kind_from_def_id(trait_))
48 {
49 Some(ty::ClosureKind::FnOnce) => Adjustment::Identity,
50 Some(ty::ClosureKind::Fn) => Adjustment::Deref { source: DerefSource::ImmRef },
51 Some(ty::ClosureKind::FnMut) => Adjustment::Deref { source: DerefSource::MutRef },
52 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),
53 };
54
55 build_call_shim(tcx, shim, Some(adjustment), CallKind::Indirect(ty))
56 }
57 ty::ShimKind::Reify(def_id, _) => {
63 build_call_shim(tcx, shim, None, CallKind::Direct(def_id))
64 }
65 ty::ShimKind::ClosureOnce { call_once: _, closure: _, track_caller: _ } => {
66 let fn_mut = tcx.require_lang_item(LangItem::FnMut, DUMMY_SP);
67 let call_mut = tcx
68 .associated_items(fn_mut)
69 .in_definition_order()
70 .find(|it| it.is_fn())
71 .unwrap()
72 .def_id;
73
74 build_call_shim(tcx, shim, Some(Adjustment::RefMut), CallKind::Direct(call_mut))
75 }
76
77 ty::ShimKind::ConstructCoroutineInClosure { coroutine_closure_def_id, receiver_by_ref } => {
78 build_construct_coroutine_by_move_shim(tcx, coroutine_closure_def_id, receiver_by_ref)
79 }
80
81 ty::ShimKind::DropGlue(def_id, ty) => {
82 if let Some(&ty::Coroutine(coroutine_def_id, args)) = ty.map(Ty::kind) {
85 let coroutine_body = tcx.optimized_mir(coroutine_def_id);
86
87 let ty::Coroutine(_, id_args) = *tcx.type_of(coroutine_def_id).skip_binder().kind()
88 else {
89 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
90 };
91
92 let body = if id_args.as_coroutine().kind_ty() == args.as_coroutine().kind_ty() {
98 coroutine_body.coroutine_drop().unwrap()
99 } else {
100 {
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!(
101 args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
102 ty::ClosureKind::FnOnce
103 );
104 tcx.optimized_mir(tcx.coroutine_by_move_body_def_id(coroutine_def_id))
105 .coroutine_drop()
106 .unwrap()
107 };
108
109 let mut body =
110 EarlyBinder::bind(tcx, body.clone()).instantiate(tcx, args).skip_norm_wip();
111 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_mir_transform/src/shim.rs:111",
"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(111u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
112
113 pm::run_passes(
114 tcx,
115 &mut body,
116 &[
117 &mentioned_items::MentionedItems,
118 &abort_unwinding_calls::AbortUnwindingCalls,
119 &add_call_guards::CriticalCallEdges,
120 ],
121 Some(MirPhase::Runtime(RuntimePhase::Optimized)),
122 pm::Optimizations::Allowed,
123 );
124
125 return body;
126 }
127
128 build_drop_shim(tcx, def_id, ty, ty::TypingEnv::post_analysis(tcx, def_id))
129 }
130 ty::ShimKind::ThreadLocal(..) => build_thread_local_shim(tcx, shim),
131 ty::ShimKind::Clone(def_id, ty) => build_clone_shim(tcx, def_id, ty),
132 ty::ShimKind::FnPtrAddr(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty),
133 ty::ShimKind::FutureDropPoll(def_id, proxy_ty, impl_ty) => {
134 let mut body =
135 async_destructor_ctor::build_future_drop_poll_shim(tcx, def_id, proxy_ty, impl_ty);
136
137 pm::run_passes(
138 tcx,
139 &mut body,
140 &[
141 &mentioned_items::MentionedItems,
142 &abort_unwinding_calls::AbortUnwindingCalls,
143 &add_call_guards::CriticalCallEdges,
144 ],
145 Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
146 pm::Optimizations::Allowed,
147 );
148 run_optimization_passes(tcx, &mut body);
149 {
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:149",
"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(149u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
150 return body;
151 }
152 ty::ShimKind::AsyncDropGlue(def_id, ty) => {
153 let mut body = async_destructor_ctor::build_async_drop_shim(tcx, def_id, ty);
154
155 pm::run_passes_no_validate(
159 tcx,
160 &mut body,
161 &[
162 &mentioned_items::MentionedItems,
163 &abort_unwinding_calls::AbortUnwindingCalls,
164 &add_call_guards::CriticalCallEdges,
165 &simplify::SimplifyCfg::MakeShim,
166 &crate::coroutine::StateTransform,
167 ],
168 Some(MirPhase::Runtime(RuntimePhase::PostCleanup)),
169 );
170 run_optimization_passes(tcx, &mut body);
171 {
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:171",
"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(171u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
172 return body;
173 }
174
175 ty::ShimKind::AsyncDropGlueCtor(def_id, ty) => {
176 let body = async_destructor_ctor::build_async_destructor_ctor_shim(tcx, def_id, ty);
177 {
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:177",
"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(177u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = {:?}", shim, body);
178 return body;
179 }
180 };
181 {
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:181",
"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(181u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = untransformed {1:?}",
shim, result) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = untransformed {:?}", shim, result);
182
183 deref_finder(tcx, &mut result, false);
184
185 pm::run_passes_no_validate(
190 tcx,
191 &mut result,
192 &[
193 &mentioned_items::MentionedItems,
194 &add_moves_for_packed_drops::AddMovesForPackedDrops,
195 &remove_noop_landing_pads::RemoveNoopLandingPads,
196 &simplify::SimplifyCfg::MakeShim,
197 &instsimplify::InstSimplify::BeforeInline,
198 &inline::ForceInline,
200 &abort_unwinding_calls::AbortUnwindingCalls,
201 &add_call_guards::CriticalCallEdges,
202 ],
203 Some(MirPhase::Runtime(RuntimePhase::Optimized)),
204 );
205
206 {
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:206",
"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(206u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, result) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("make_shim({:?}) = {:?}", shim, result);
207
208 result
209}
210
211#[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)]
212enum DerefSource {
213 ImmRef,
215 MutRef,
217 MutPtr,
219}
220
221#[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)]
222enum Adjustment {
223 Identity,
225
226 Deref { source: DerefSource },
231
232 RefMut,
237}
238
239#[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)]
240enum CallKind<'tcx> {
241 Indirect(Ty<'tcx>),
243
244 Direct(DefId),
246}
247
248fn local_decls_for_sig<'tcx>(
249 sig: &ty::FnSig<'tcx>,
250 span: Span,
251) -> IndexVec<Local, LocalDecl<'tcx>> {
252 iter::once(LocalDecl::new(sig.output(), span))
253 .chain(sig.inputs().iter().map(|ity| LocalDecl::new(*ity, span).immutable()))
254 .collect()
255}
256
257pub fn build_drop_shim<'tcx>(
262 tcx: TyCtxt<'tcx>,
263 def_id: DefId,
264 ty: Option<Ty<'tcx>>,
265 typing_env: ty::TypingEnv<'tcx>,
266) -> Body<'tcx> {
267 {
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:267",
"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(267u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("build_drop_shim(def_id={0:?}, ty={1:?})",
def_id, ty) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
268
269 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()));
270
271 let args = if let Some(ty) = ty {
272 tcx.mk_args(&[ty.into()])
273 } else {
274 GenericArgs::identity_for_item(tcx, def_id)
275 };
276 let sig = tcx.fn_sig(def_id).instantiate(tcx, args).skip_norm_wip();
277 let sig = tcx.instantiate_bound_regions_with_erased(sig);
278 let span = tcx.def_span(def_id);
279
280 let source_info = SourceInfo::outermost(span);
281
282 let return_block = BasicBlock::new(1);
283 let mut blocks = IndexVec::with_capacity(2);
284 let block = |blocks: &mut IndexVec<_, _>, kind| {
285 blocks.push(BasicBlockData::new(
286 Some(Terminator { source_info, kind, attributes: ThinVec::new() }),
287 false,
288 ))
289 };
290 if ty.is_some() {
291 block(&mut blocks, TerminatorKind::Goto { target: return_block });
292 }
293 block(&mut blocks, TerminatorKind::Return);
294
295 let source = MirSource::from_shim(ty::ShimKind::DropGlue(def_id, ty));
296 let mut body =
297 new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
298
299 let Some(ty) = ty else {
300 return body;
301 };
302
303 let dropee_ptr = Place::from(Local::arg(0));
304
305 if let ty::Array(ety, _len) = *ty.kind() {
306 let slice_ty = Ty::new_slice(tcx, ety);
309 let mut_slice_ty = Ty::new_ref(tcx, tcx.lifetimes.re_erased, slice_ty, ty::Mutability::Mut);
310 let erased_local = body.local_decls.push(LocalDecl::new(mut_slice_ty, span));
311
312 let start = &mut body.basic_blocks_mut()[START_BLOCK];
313 start.statements.push(Statement::new(
314 source_info,
315 StatementKind::Assign(Box::new((
316 Place::from(erased_local),
317 Rvalue::Cast(
318 CastKind::PointerCoercion(
319 ty::adjustment::PointerCoercion::Unsize,
320 CoercionSource::Implicit,
321 ),
322 Operand::Move(dropee_ptr),
323 mut_slice_ty,
324 ),
325 ))),
326 ));
327 start.terminator = Some(Terminator {
328 source_info,
329 kind: TerminatorKind::Call {
330 func: Operand::function_handle(
332 tcx,
333 def_id,
334 ty::Binder::dummy([ty::GenericArg::from(slice_ty)]),
335 span,
336 ),
337 args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]),
338 destination: Place::from(RETURN_PLACE),
339 target: Some(return_block),
340 unwind: UnwindAction::Continue,
341 call_source: CallSource::Misc,
342 fn_span: span,
343 },
344 attributes: ThinVec::new(),
345 });
346 } else {
347 let patch = {
348 let mut elaborator = DropShimElaborator {
349 body: &body,
350 patch: MirPatch::new(&body),
351 tcx,
352 typing_env,
353 produce_async_drops: false,
354 };
355 let dropee = tcx.mk_place_deref(dropee_ptr);
356 let resume_block = elaborator.patch.resume_block();
357 elaborate_drop(
358 &mut elaborator,
359 source_info,
360 dropee,
361 (),
362 return_block,
363 Unwind::To(resume_block),
364 START_BLOCK,
365 None,
366 );
367 elaborator.patch
368 };
369 patch.apply(&mut body);
370 }
371
372 body
373}
374
375fn new_body<'tcx>(
376 source: MirSource<'tcx>,
377 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
378 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
379 arg_count: usize,
380 span: Span,
381) -> Body<'tcx> {
382 let mut body = Body::new(
383 source,
384 basic_blocks,
385 IndexVec::from_elem_n(
386 SourceScopeData {
387 span,
388 parent_scope: None,
389 inlined: None,
390 inlined_parent_scope: None,
391 local_data: ClearCrossCrate::Clear,
392 },
393 1,
394 ),
395 local_decls,
396 IndexVec::new(),
397 arg_count,
398 ::alloc::vec::Vec::new()vec![],
399 span,
400 None,
401 None,
403 );
404 body.set_required_consts(Vec::new());
406 body
407}
408
409pub(super) struct DropShimElaborator<'a, 'tcx> {
410 pub body: &'a Body<'tcx>,
411 pub patch: MirPatch<'tcx>,
412 pub tcx: TyCtxt<'tcx>,
413 pub typing_env: ty::TypingEnv<'tcx>,
414 pub produce_async_drops: bool,
415}
416
417impl fmt::Debug for DropShimElaborator<'_, '_> {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
419 f.debug_struct("DropShimElaborator").finish_non_exhaustive()
420 }
421}
422
423impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
424 type Path = ();
425
426 fn patch_ref(&self) -> &MirPatch<'tcx> {
427 &self.patch
428 }
429 fn patch(&mut self) -> &mut MirPatch<'tcx> {
430 &mut self.patch
431 }
432 fn body(&self) -> &'a Body<'tcx> {
433 self.body
434 }
435 fn tcx(&self) -> TyCtxt<'tcx> {
436 self.tcx
437 }
438 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
439 self.typing_env
440 }
441
442 fn allow_async_drops(&self) -> bool {
443 self.produce_async_drops
444 }
445
446 fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
447 match mode {
448 DropFlagMode::Shallow => {
449 DropStyle::Static
452 }
453 DropFlagMode::Deep => {
454 DropStyle::Open
457 }
458 }
459 }
460
461 fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
462 None
463 }
464
465 fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {}
466
467 fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option<Self::Path> {
468 None
469 }
470 fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
471 None
472 }
473 fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
474 Some(())
475 }
476 fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
477 None
478 }
479}
480
481fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> {
482 let def_id = shim.def_id();
483
484 let span = tcx.def_span(def_id);
485 let source_info = SourceInfo::outermost(span);
486
487 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,
attributes: ThinVec::new(),
}), false)]))vec![BasicBlockData::new_stmts(
488 vec![Statement::new(
489 source_info,
490 StatementKind::Assign(Box::new((
491 Place::return_place(),
492 Rvalue::ThreadLocalRef(def_id),
493 ))),
494 )],
495 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
496 false,
497 )]);
498
499 new_body(
500 MirSource::from_shim(shim),
501 blocks,
502 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)]),
503 0,
504 span,
505 )
506}
507
508fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
510 {
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:510",
"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(510u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("build_clone_shim(def_id={0:?})",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("build_clone_shim(def_id={:?})", def_id);
511
512 let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
513
514 let dest = Place::return_place();
515 let src = tcx.mk_place_deref(Place::from(Local::arg(0)));
516
517 match self_ty.kind() {
518 ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
519 ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
520 ty::CoroutineClosure(_, args) => {
521 builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
522 }
523 ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
524 ty::Coroutine(coroutine_def_id, args) => {
525 {
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);
526 builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine())
527 }
528 _ => ::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),
529 };
530
531 builder.into_mir()
532}
533
534struct CloneShimBuilder<'tcx> {
535 tcx: TyCtxt<'tcx>,
536 def_id: DefId,
537 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
538 blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
539 span: Span,
540 sig: ty::FnSig<'tcx>,
541}
542
543impl<'tcx> CloneShimBuilder<'tcx> {
544 fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
545 let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip();
549 let sig = tcx.instantiate_bound_regions_with_erased(sig);
550 let span = tcx.def_span(def_id);
551
552 CloneShimBuilder {
553 tcx,
554 def_id,
555 local_decls: local_decls_for_sig(&sig, span),
556 blocks: IndexVec::new(),
557 span,
558 sig,
559 }
560 }
561
562 fn into_mir(self) -> Body<'tcx> {
563 let source =
564 MirSource::from_shim(ty::ShimKind::Clone(self.def_id, self.sig.inputs_and_output[0]));
565 new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
566 }
567
568 fn source_info(&self) -> SourceInfo {
569 SourceInfo::outermost(self.span)
570 }
571
572 fn block(
573 &mut self,
574 statements: Vec<Statement<'tcx>>,
575 kind: TerminatorKind<'tcx>,
576 is_cleanup: bool,
577 ) -> BasicBlock {
578 let source_info = self.source_info();
579 self.blocks.push(BasicBlockData::new_stmts(
580 statements,
581 Some(Terminator { source_info, kind, attributes: ThinVec::new() }),
582 is_cleanup,
583 ))
584 }
585
586 fn block_index_offset(&self, offset: usize) -> BasicBlock {
591 BasicBlock::new(self.blocks.len() + offset)
592 }
593
594 fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
595 Statement::new(self.source_info(), kind)
596 }
597
598 fn copy_shim(&mut self) {
599 let rcvr = self.tcx.mk_place_deref(Place::from(Local::arg(0)));
600 let ret_statement = self.make_statement(StatementKind::Assign(Box::new((
601 Place::return_place(),
602 Rvalue::Use(Operand::Copy(rcvr), WithRetag::Yes),
603 ))));
604 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);
605 }
606
607 fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
608 let span = self.span;
609 let mut local = LocalDecl::new(ty, span);
610 if mutability.is_not() {
611 local = local.immutable();
612 }
613 Place::from(self.local_decls.push(local))
614 }
615
616 fn make_clone_call(
617 &mut self,
618 dest: Place<'tcx>,
619 src: Place<'tcx>,
620 ty: Ty<'tcx>,
621 next: BasicBlock,
622 cleanup: BasicBlock,
623 ) {
624 let tcx = self.tcx;
625
626 let func_ty = Ty::new_fn_def(tcx, self.def_id, ty::Binder::dummy([ty]));
629 let func = Operand::Constant(Box::new(ConstOperand {
630 span: self.span,
631 user_ty: None,
632 const_: Const::zero_sized(func_ty),
633 }));
634
635 let ref_loc =
636 self.make_place(Mutability::Not, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty));
637
638 let statement = self.make_statement(StatementKind::Assign(Box::new((
640 ref_loc,
641 Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src),
642 ))));
643
644 self.block(
646 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
647 TerminatorKind::Call {
648 func,
649 args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
650 destination: dest,
651 target: Some(next),
652 unwind: UnwindAction::Cleanup(cleanup),
653 call_source: CallSource::Normal,
654 fn_span: self.span,
655 },
656 false,
657 );
658 }
659
660 fn clone_fields<I>(
661 &mut self,
662 dest: Place<'tcx>,
663 src: Place<'tcx>,
664 target: BasicBlock,
665 mut unwind: BasicBlock,
666 tys: I,
667 ) -> BasicBlock
668 where
669 I: IntoIterator<Item = Ty<'tcx>>,
670 {
671 for (i, ity) in tys.into_iter().enumerate() {
673 let field = FieldIdx::new(i);
684 let src_field = self.tcx.mk_place_field(src, field, ity);
685
686 let dest_field = self.tcx.mk_place_field(dest, field, ity);
687
688 let next_unwind = self.block_index_offset(1);
689 let next_block = self.block_index_offset(2);
690 self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
691 self.block(
692 ::alloc::vec::Vec::new()vec![],
693 TerminatorKind::Drop {
694 place: dest_field,
695 target: unwind,
696 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
697 replace: false,
698 drop: None,
699 },
700 true,
701 );
702 unwind = next_unwind;
703 }
704 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target }, false);
706 unwind
707 }
708
709 fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
710 where
711 I: IntoIterator<Item = Ty<'tcx>>,
712 {
713 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
714 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
715 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
716
717 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
718 }
719
720 fn coroutine_shim(
721 &mut self,
722 dest: Place<'tcx>,
723 src: Place<'tcx>,
724 coroutine_def_id: DefId,
725 args: CoroutineArgs<TyCtxt<'tcx>>,
726 ) {
727 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
728 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
729 let switch = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
731 let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
732 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
733 let unreachable = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
734 let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count());
735 for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() {
736 let variant_index = VariantIdx::new(index);
737 let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
738 let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
739 let clone_block = self.block_index_offset(1);
740 let start_block = self.block(
741 ::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 {
742 place: Box::new(Place::return_place()),
743 variant_index,
744 })],
745 TerminatorKind::Goto { target: clone_block },
746 false,
747 );
748 cases.push((index as u128, start_block));
749 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
750 }
751 let discr_ty = args.discr_ty(self.tcx);
752 let temp = self.make_place(Mutability::Mut, discr_ty);
753 let rvalue = Rvalue::Discriminant(src);
754 let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
755 match &mut self.blocks[switch] {
756 BasicBlockData { statements, terminator: Some(Terminator { kind, .. }), .. } => {
757 statements.push(statement);
758 *kind = TerminatorKind::SwitchInt {
759 discr: Operand::Move(temp),
760 targets: SwitchTargets::new(cases.into_iter(), unreachable),
761 };
762 }
763 BasicBlockData { terminator: None, .. } => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
764 }
765 }
766}
767
768x;#[instrument(level = "debug", skip(tcx), ret)]
771fn build_call_shim<'tcx>(
772 tcx: TyCtxt<'tcx>,
773 shim: ty::ShimKind<'tcx>,
774 rcvr_adjustment: Option<Adjustment>,
775 call_kind: CallKind<'tcx>,
776) -> Body<'tcx> {
777 let (sig_args, untuple_args) = if let ty::ShimKind::FnPtr(_, ty) = shim {
781 let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
782
783 let untuple_args = sig.inputs();
784
785 let arg_tup = Ty::new_tup(tcx, untuple_args);
787
788 (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
789 } else {
790 (None, None)
791 };
792
793 let def_id = shim.def_id();
794
795 let sig = tcx.fn_sig(def_id);
796 let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
797
798 assert_eq!(sig_args.is_some(), !shim.has_polymorphic_mir_body());
799 let mut sig = if let Some(sig_args) = sig_args {
800 sig.instantiate(tcx, &sig_args).skip_norm_wip()
801 } else {
802 sig.instantiate_identity().skip_norm_wip()
803 };
804
805 if let CallKind::Indirect(fnty) = call_kind {
806 let mut inputs_and_output = sig.inputs_and_output.to_vec();
812
813 assert_eq!(inputs_and_output.len(), 3);
816
817 let self_arg = &mut inputs_and_output[0];
820 *self_arg = match rcvr_adjustment.unwrap() {
821 Adjustment::Identity => fnty,
822 Adjustment::Deref { source } => match source {
823 DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
824 DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
825 DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
826 },
827 Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {shim:?}"),
828 };
829 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
830 }
831
832 if let ty::ShimKind::VTable(..) = shim {
835 let mut inputs_and_output = sig.inputs_and_output.to_vec();
837 let self_arg = &mut inputs_and_output[0];
838 debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
839 *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
840 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
841 }
842
843 let span = tcx.def_span(def_id);
844
845 debug!(?sig);
846
847 let mut local_decls = local_decls_for_sig(&sig, span);
848 let source_info = SourceInfo::outermost(span);
849
850 let destination = Place::return_place();
851
852 let rcvr_place = || {
853 assert!(rcvr_adjustment.is_some());
854 Place::from(Local::arg(0))
855 };
856 let mut statements = vec![];
857
858 let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
859 Adjustment::Identity => Operand::Move(rcvr_place()),
860 Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())),
861 Adjustment::RefMut => {
862 let ref_rcvr = local_decls.push(
864 LocalDecl::new(
865 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, sig.inputs()[0]),
866 span,
867 )
868 .immutable(),
869 );
870 let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
871 statements.push(Statement::new(
872 source_info,
873 StatementKind::Assign(Box::new((
874 Place::from(ref_rcvr),
875 Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
876 ))),
877 ));
878 Operand::Move(Place::from(ref_rcvr))
879 }
880 });
881
882 let (callee, mut args) = match call_kind {
883 CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
885
886 CallKind::Direct(def_id) => {
888 let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
889 (
890 Operand::Constant(Box::new(ConstOperand {
891 span,
892 user_ty: None,
893 const_: Const::zero_sized(ty),
894 })),
895 rcvr.into_iter().collect::<Vec<_>>(),
896 )
897 }
898 };
899
900 let mut arg_range = 0..sig.inputs().len();
901
902 if rcvr_adjustment.is_some() {
904 arg_range.start += 1;
905 }
906
907 if untuple_args.is_some() {
909 arg_range.end -= 1;
910 }
911
912 args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::arg(i)))));
914
915 if let Some(untuple_args) = untuple_args {
917 let tuple_arg = Local::arg(sig.inputs().len() - 1);
918 args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
919 Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity))
920 }));
921 }
922
923 let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
924 let mut blocks = IndexVec::with_capacity(n_blocks);
925 let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
926 blocks.push(BasicBlockData::new_stmts(
927 statements,
928 Some(Terminator { source_info, kind, attributes: ThinVec::new() }),
929 is_cleanup,
930 ))
931 };
932
933 let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
935 block(
936 &mut blocks,
937 statements,
938 TerminatorKind::Call {
939 func: callee,
940 args,
941 destination,
942 target: Some(BasicBlock::new(1)),
943 unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
944 UnwindAction::Cleanup(BasicBlock::new(3))
945 } else {
946 UnwindAction::Continue
947 },
948 call_source: CallSource::Misc,
949 fn_span: span,
950 },
951 false,
952 );
953
954 if let Some(Adjustment::RefMut) = rcvr_adjustment {
955 block(
957 &mut blocks,
958 vec![],
959 TerminatorKind::Drop {
960 place: rcvr_place(),
961 target: BasicBlock::new(2),
962 unwind: UnwindAction::Continue,
963 replace: false,
964 drop: None,
965 },
966 false,
967 );
968 }
969 let stmts = vec![];
971 block(&mut blocks, stmts, TerminatorKind::Return, false);
972 if let Some(Adjustment::RefMut) = rcvr_adjustment {
973 block(
975 &mut blocks,
976 vec![],
977 TerminatorKind::Drop {
978 place: rcvr_place(),
979 target: BasicBlock::new(4),
980 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
981 replace: false,
982 drop: None,
983 },
984 true,
985 );
986
987 block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
989 }
990
991 let mut body =
992 new_body(MirSource::from_shim(shim), blocks, local_decls, sig.inputs().len(), span);
993
994 if let ExternAbi::RustCall = sig.abi() {
995 body.spread_arg = Some(Local::new(sig.inputs().len()));
996 }
997
998 body
999}
1000
1001pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
1002 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));
1003
1004 let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
1005
1006 let sig = tcx
1008 .fn_sig(ctor_id)
1009 .instantiate_identity()
1010 .skip_norm_wip()
1011 .no_bound_vars()
1012 .expect("LBR in ADT constructor signature");
1013 let sig = tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(sig));
1014
1015 let ty::Adt(adt_def, args) = sig.output().kind() else {
1016 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type for ADT ctor {0:?}",
sig.output()));bug!("unexpected type for ADT ctor {:?}", sig.output());
1017 };
1018
1019 {
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:1019",
"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(1019u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("build_ctor: ctor_id={0:?} sig={1:?}",
ctor_id, sig) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
1020
1021 let span = tcx.def_span(ctor_id);
1022
1023 let local_decls = local_decls_for_sig(&sig, span);
1024
1025 let source_info = SourceInfo::outermost(span);
1026
1027 let variant_index =
1028 if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
1029
1030 {
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:1036",
"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(1036u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("build_ctor: variant_index={0:?}",
variant_index) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("build_ctor: variant_index={:?}", variant_index);
1037
1038 let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None);
1039 let variant = adt_def.variant(variant_index);
1040 let statement = Statement::new(
1041 source_info,
1042 StatementKind::Assign(Box::new((
1043 Place::return_place(),
1044 Rvalue::Aggregate(
1045 Box::new(kind),
1046 (0..variant.fields.len())
1047 .map(|idx| Operand::Move(Place::from(Local::arg(idx))))
1048 .collect(),
1049 ),
1050 ))),
1051 );
1052
1053 let start_block = BasicBlockData::new_stmts(
1054 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
1055 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1056 false,
1057 );
1058
1059 let source = MirSource::item(ctor_id);
1060 let mut body = new_body(
1061 source,
1062 IndexVec::from_elem_n(start_block, 1),
1063 local_decls,
1064 sig.inputs().len(),
1065 span,
1066 );
1067 body.set_mentioned_items(Vec::new());
1070
1071 pm::run_passes_no_validate(
1074 tcx,
1075 &mut body,
1076 &[],
1077 Some(MirPhase::Runtime(RuntimePhase::Optimized)),
1078 );
1079
1080 body
1081}
1082
1083fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
1091 {
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}");
1092 let span = tcx.def_span(def_id);
1093 let Some(sig) =
1094 tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip().no_bound_vars()
1095 else {
1096 ::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}`");
1097 };
1098 let locals = local_decls_for_sig(&sig, span);
1099
1100 let source_info = SourceInfo::outermost(span);
1101 let rvalue = Rvalue::Cast(
1104 CastKind::FnPtrToPtr,
1105 Operand::Move(Place::from(Local::arg(0))),
1106 Ty::new_imm_ptr(tcx, tcx.types.unit),
1107 );
1108 let stmt = Statement::new(
1109 source_info,
1110 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1111 );
1112 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1113 let start_block = BasicBlockData::new_stmts(
1114 statements,
1115 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1116 false,
1117 );
1118 let source = MirSource::from_shim(ty::ShimKind::FnPtrAddr(def_id, self_ty));
1119 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1120}
1121
1122fn build_construct_coroutine_by_move_shim<'tcx>(
1123 tcx: TyCtxt<'tcx>,
1124 coroutine_closure_def_id: DefId,
1125 receiver_by_ref: bool,
1126) -> Body<'tcx> {
1127 let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity().skip_norm_wip();
1128 let mut self_local: Place<'tcx> = Local::arg(0).into();
1129 let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
1130 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1131 };
1132
1133 if receiver_by_ref {
1139 self_local = tcx.mk_place_deref(self_local);
1140 self_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, self_ty);
1141 }
1142
1143 let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
1144 tcx.mk_fn_sig(
1145 [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
1146 sig.to_coroutine_given_kind_and_upvars(
1147 tcx,
1148 args.as_coroutine_closure().parent_args(),
1149 tcx.coroutine_for_closure(coroutine_closure_def_id),
1150 ty::ClosureKind::FnOnce,
1151 tcx.lifetimes.re_erased,
1152 args.as_coroutine_closure().tupled_upvars_ty(),
1153 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
1154 ),
1155 sig.fn_sig_kind,
1156 )
1157 });
1158 let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
1159 let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else {
1160 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1161 };
1162
1163 let span = tcx.def_span(coroutine_closure_def_id);
1164 let locals = local_decls_for_sig(&sig, span);
1165
1166 let mut fields = ::alloc::vec::Vec::new()vec![];
1167
1168 for idx in 1..sig.inputs().len() {
1170 fields.push(Operand::Move(Local::arg(idx).into()));
1171 }
1172
1173 for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
1174 if receiver_by_ref {
1175 if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Ref(_, _, hir::Mutability::Not) => true,
_ => false,
}matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
1179 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!(
1183 "field should be captured by immutable ref if we have \
1184 an `Fn` instance, but it was: {ty}"
1185 ));
1186 }
1187 fields.push(Operand::Copy(tcx.mk_place_field(
1188 self_local,
1189 FieldIdx::from_usize(idx),
1190 ty,
1191 )));
1192 } else {
1193 fields.push(Operand::Move(tcx.mk_place_field(
1194 self_local,
1195 FieldIdx::from_usize(idx),
1196 ty,
1197 )));
1198 }
1199 }
1200
1201 let source_info = SourceInfo::outermost(span);
1202 let rvalue = Rvalue::Aggregate(
1203 Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)),
1204 IndexVec::from_raw(fields),
1205 );
1206 let stmt = Statement::new(
1207 source_info,
1208 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1209 );
1210 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1211 let start_block = BasicBlockData::new_stmts(
1212 statements,
1213 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1214 false,
1215 );
1216
1217 let source = MirSource::from_shim(ty::ShimKind::ConstructCoroutineInClosure {
1218 coroutine_closure_def_id,
1219 receiver_by_ref,
1220 });
1221
1222 let body =
1223 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
1224
1225 let pass_name =
1226 if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" };
1227 if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) {
1228 dumper.dump_mir(&body);
1229 }
1230
1231 body
1232}