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