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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?})",
shim) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, body) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = untransformed {1:?}",
shim, result) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("make_shim({0:?}) = {1:?}",
shim, result) as &dyn 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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("build_drop_shim(def_id={0:?}, ty={1:?})",
def_id, ty) as &dyn Value))])
});
} else { ; }
};debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
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(tcx, def_id, [ty::GenericArg::from(slice_ty)], span),
331 args: Box::new([Spanned { span, node: Operand::Move(Place::from(erased_local)) }]),
332 destination: Place::from(RETURN_PLACE),
333 target: Some(return_block),
334 unwind: UnwindAction::Continue,
335 call_source: CallSource::Misc,
336 fn_span: span,
337 },
338 attributes: ThinVec::new(),
339 });
340 } else {
341 let patch = {
342 let mut elaborator = DropShimElaborator {
343 body: &body,
344 patch: MirPatch::new(&body),
345 tcx,
346 typing_env,
347 produce_async_drops: false,
348 };
349 let dropee = tcx.mk_place_deref(dropee_ptr);
350 let resume_block = elaborator.patch.resume_block();
351 elaborate_drop(
352 &mut elaborator,
353 source_info,
354 dropee,
355 (),
356 return_block,
357 Unwind::To(resume_block),
358 START_BLOCK,
359 None,
360 );
361 elaborator.patch
362 };
363 patch.apply(&mut body);
364 }
365
366 body
367}
368
369fn new_body<'tcx>(
370 source: MirSource<'tcx>,
371 basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
372 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
373 arg_count: usize,
374 span: Span,
375) -> Body<'tcx> {
376 let mut body = Body::new(
377 source,
378 basic_blocks,
379 IndexVec::from_elem_n(
380 SourceScopeData {
381 span,
382 parent_scope: None,
383 inlined: None,
384 inlined_parent_scope: None,
385 local_data: ClearCrossCrate::Clear,
386 },
387 1,
388 ),
389 local_decls,
390 IndexVec::new(),
391 arg_count,
392 ::alloc::vec::Vec::new()vec![],
393 span,
394 None,
395 None,
397 );
398 body.set_required_consts(Vec::new());
400 body
401}
402
403pub(super) struct DropShimElaborator<'a, 'tcx> {
404 pub body: &'a Body<'tcx>,
405 pub patch: MirPatch<'tcx>,
406 pub tcx: TyCtxt<'tcx>,
407 pub typing_env: ty::TypingEnv<'tcx>,
408 pub produce_async_drops: bool,
409}
410
411impl fmt::Debug for DropShimElaborator<'_, '_> {
412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
413 f.debug_struct("DropShimElaborator").finish_non_exhaustive()
414 }
415}
416
417impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
418 type Path = ();
419
420 fn patch_ref(&self) -> &MirPatch<'tcx> {
421 &self.patch
422 }
423 fn patch(&mut self) -> &mut MirPatch<'tcx> {
424 &mut self.patch
425 }
426 fn body(&self) -> &'a Body<'tcx> {
427 self.body
428 }
429 fn tcx(&self) -> TyCtxt<'tcx> {
430 self.tcx
431 }
432 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
433 self.typing_env
434 }
435
436 fn allow_async_drops(&self) -> bool {
437 self.produce_async_drops
438 }
439
440 fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
441 match mode {
442 DropFlagMode::Shallow => {
443 DropStyle::Static
446 }
447 DropFlagMode::Deep => {
448 DropStyle::Open
451 }
452 }
453 }
454
455 fn get_drop_flag(&mut self, _path: Self::Path) -> Option<Operand<'tcx>> {
456 None
457 }
458
459 fn clear_drop_flag(&mut self, _location: Location, _path: Self::Path, _mode: DropFlagMode) {}
460
461 fn field_subpath(&self, _path: Self::Path, _field: FieldIdx) -> Option<Self::Path> {
462 None
463 }
464 fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
465 None
466 }
467 fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> {
468 Some(())
469 }
470 fn array_subpath(&self, _path: Self::Path, _index: u64, _size: u64) -> Option<Self::Path> {
471 None
472 }
473}
474
475fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Body<'tcx> {
476 let def_id = shim.def_id();
477
478 let span = tcx.def_span(def_id);
479 let source_info = SourceInfo::outermost(span);
480
481 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(
482 vec![Statement::new(
483 source_info,
484 StatementKind::Assign(Box::new((
485 Place::return_place(),
486 Rvalue::ThreadLocalRef(def_id),
487 ))),
488 )],
489 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
490 false,
491 )]);
492
493 new_body(
494 MirSource::from_shim(shim),
495 blocks,
496 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)]),
497 0,
498 span,
499 )
500}
501
502fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
504 {
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:504",
"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(504u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("build_clone_shim(def_id={0:?})",
def_id) as &dyn Value))])
});
} else { ; }
};debug!("build_clone_shim(def_id={:?})", def_id);
505
506 let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty);
507
508 let dest = Place::return_place();
509 let src = tcx.mk_place_deref(Place::from(Local::arg(0)));
510
511 match self_ty.kind() {
512 ty::FnDef(..) | ty::FnPtr(..) => builder.copy_shim(),
513 ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()),
514 ty::CoroutineClosure(_, args) => {
515 builder.tuple_like_shim(dest, src, args.as_coroutine_closure().upvar_tys())
516 }
517 ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()),
518 ty::Coroutine(coroutine_def_id, args) => {
519 {
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);
520 builder.coroutine_shim(dest, src, *coroutine_def_id, args.as_coroutine())
521 }
522 _ => ::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),
523 };
524
525 builder.into_mir()
526}
527
528struct CloneShimBuilder<'tcx> {
529 tcx: TyCtxt<'tcx>,
530 def_id: DefId,
531 local_decls: IndexVec<Local, LocalDecl<'tcx>>,
532 blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
533 span: Span,
534 sig: ty::FnSig<'tcx>,
535}
536
537impl<'tcx> CloneShimBuilder<'tcx> {
538 fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
539 let sig = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip();
543 let sig = tcx.instantiate_bound_regions_with_erased(sig);
544 let span = tcx.def_span(def_id);
545
546 CloneShimBuilder {
547 tcx,
548 def_id,
549 local_decls: local_decls_for_sig(&sig, span),
550 blocks: IndexVec::new(),
551 span,
552 sig,
553 }
554 }
555
556 fn into_mir(self) -> Body<'tcx> {
557 let source =
558 MirSource::from_shim(ty::ShimKind::Clone(self.def_id, self.sig.inputs_and_output[0]));
559 new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
560 }
561
562 fn source_info(&self) -> SourceInfo {
563 SourceInfo::outermost(self.span)
564 }
565
566 fn block(
567 &mut self,
568 statements: Vec<Statement<'tcx>>,
569 kind: TerminatorKind<'tcx>,
570 is_cleanup: bool,
571 ) -> BasicBlock {
572 let source_info = self.source_info();
573 self.blocks.push(BasicBlockData::new_stmts(
574 statements,
575 Some(Terminator { source_info, kind, attributes: ThinVec::new() }),
576 is_cleanup,
577 ))
578 }
579
580 fn block_index_offset(&self, offset: usize) -> BasicBlock {
585 BasicBlock::new(self.blocks.len() + offset)
586 }
587
588 fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> {
589 Statement::new(self.source_info(), kind)
590 }
591
592 fn copy_shim(&mut self) {
593 let rcvr = self.tcx.mk_place_deref(Place::from(Local::arg(0)));
594 let ret_statement = self.make_statement(StatementKind::Assign(Box::new((
595 Place::return_place(),
596 Rvalue::Use(Operand::Copy(rcvr), WithRetag::Yes),
597 ))));
598 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);
599 }
600
601 fn make_place(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Place<'tcx> {
602 let span = self.span;
603 let mut local = LocalDecl::new(ty, span);
604 if mutability.is_not() {
605 local = local.immutable();
606 }
607 Place::from(self.local_decls.push(local))
608 }
609
610 fn make_clone_call(
611 &mut self,
612 dest: Place<'tcx>,
613 src: Place<'tcx>,
614 ty: Ty<'tcx>,
615 next: BasicBlock,
616 cleanup: BasicBlock,
617 ) {
618 let tcx = self.tcx;
619
620 let func_ty = Ty::new_fn_def(tcx, self.def_id, [ty]);
622 let func = Operand::Constant(Box::new(ConstOperand {
623 span: self.span,
624 user_ty: None,
625 const_: Const::zero_sized(func_ty),
626 }));
627
628 let ref_loc =
629 self.make_place(Mutability::Not, Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, ty));
630
631 let statement = self.make_statement(StatementKind::Assign(Box::new((
633 ref_loc,
634 Rvalue::Ref(tcx.lifetimes.re_erased, BorrowKind::Shared, src),
635 ))));
636
637 self.block(
639 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
640 TerminatorKind::Call {
641 func,
642 args: [Spanned { node: Operand::Move(ref_loc), span: DUMMY_SP }].into(),
643 destination: dest,
644 target: Some(next),
645 unwind: UnwindAction::Cleanup(cleanup),
646 call_source: CallSource::Normal,
647 fn_span: self.span,
648 },
649 false,
650 );
651 }
652
653 fn clone_fields<I>(
654 &mut self,
655 dest: Place<'tcx>,
656 src: Place<'tcx>,
657 target: BasicBlock,
658 mut unwind: BasicBlock,
659 tys: I,
660 ) -> BasicBlock
661 where
662 I: IntoIterator<Item = Ty<'tcx>>,
663 {
664 for (i, ity) in tys.into_iter().enumerate() {
666 let field = FieldIdx::new(i);
677 let src_field = self.tcx.mk_place_field(src, field, ity);
678
679 let dest_field = self.tcx.mk_place_field(dest, field, ity);
680
681 let next_unwind = self.block_index_offset(1);
682 let next_block = self.block_index_offset(2);
683 self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
684 self.block(
685 ::alloc::vec::Vec::new()vec![],
686 TerminatorKind::Drop {
687 place: dest_field,
688 target: unwind,
689 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
690 replace: false,
691 drop: None,
692 },
693 true,
694 );
695 unwind = next_unwind;
696 }
697 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target }, false);
699 unwind
700 }
701
702 fn tuple_like_shim<I>(&mut self, dest: Place<'tcx>, src: Place<'tcx>, tys: I)
703 where
704 I: IntoIterator<Item = Ty<'tcx>>,
705 {
706 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
707 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
708 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
709
710 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
711 }
712
713 fn coroutine_shim(
714 &mut self,
715 dest: Place<'tcx>,
716 src: Place<'tcx>,
717 coroutine_def_id: DefId,
718 args: CoroutineArgs<TyCtxt<'tcx>>,
719 ) {
720 self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
721 let unwind = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::UnwindResume, true);
722 let switch = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
724 let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
725 let target = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Return, false);
726 let unreachable = self.block(::alloc::vec::Vec::new()vec![], TerminatorKind::Unreachable, false);
727 let mut cases = Vec::with_capacity(args.state_tys(coroutine_def_id, self.tcx).count());
728 for (index, state_tys) in args.state_tys(coroutine_def_id, self.tcx).enumerate() {
729 let variant_index = VariantIdx::new(index);
730 let dest = self.tcx.mk_place_downcast_unnamed(dest, variant_index);
731 let src = self.tcx.mk_place_downcast_unnamed(src, variant_index);
732 let clone_block = self.block_index_offset(1);
733 let start_block = self.block(
734 ::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 {
735 place: Box::new(Place::return_place()),
736 variant_index,
737 })],
738 TerminatorKind::Goto { target: clone_block },
739 false,
740 );
741 cases.push((index as u128, start_block));
742 let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, state_tys);
743 }
744 let discr_ty = args.discr_ty(self.tcx);
745 let temp = self.make_place(Mutability::Mut, discr_ty);
746 let rvalue = Rvalue::Discriminant(src);
747 let statement = self.make_statement(StatementKind::Assign(Box::new((temp, rvalue))));
748 match &mut self.blocks[switch] {
749 BasicBlockData { statements, terminator: Some(Terminator { kind, .. }), .. } => {
750 statements.push(statement);
751 *kind = TerminatorKind::SwitchInt {
752 discr: Operand::Move(temp),
753 targets: SwitchTargets::new(cases.into_iter(), unreachable),
754 };
755 }
756 BasicBlockData { terminator: None, .. } => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
757 }
758 }
759}
760
761x;#[instrument(level = "debug", skip(tcx), ret)]
764fn build_call_shim<'tcx>(
765 tcx: TyCtxt<'tcx>,
766 shim: ty::ShimKind<'tcx>,
767 rcvr_adjustment: Option<Adjustment>,
768 call_kind: CallKind<'tcx>,
769) -> Body<'tcx> {
770 let (sig_args, untuple_args) = if let ty::ShimKind::FnPtr(_, ty) = shim {
774 let sig = tcx.instantiate_bound_regions_with_erased(ty.fn_sig(tcx));
775
776 let untuple_args = sig.inputs();
777
778 let arg_tup = Ty::new_tup(tcx, untuple_args);
780
781 (Some([ty.into(), arg_tup.into()]), Some(untuple_args))
782 } else {
783 (None, None)
784 };
785
786 let def_id = shim.def_id();
787
788 let sig = tcx.fn_sig(def_id);
789 let sig = sig.map_bound(|sig| tcx.instantiate_bound_regions_with_erased(sig));
790
791 assert_eq!(sig_args.is_some(), !shim.has_polymorphic_mir_body());
792 let mut sig = if let Some(sig_args) = sig_args {
793 sig.instantiate(tcx, &sig_args).skip_norm_wip()
794 } else {
795 sig.instantiate_identity().skip_norm_wip()
796 };
797
798 if let CallKind::Indirect(fnty) = call_kind {
799 let mut inputs_and_output = sig.inputs_and_output.to_vec();
805
806 assert_eq!(inputs_and_output.len(), 3);
809
810 let self_arg = &mut inputs_and_output[0];
813 *self_arg = match rcvr_adjustment.unwrap() {
814 Adjustment::Identity => fnty,
815 Adjustment::Deref { source } => match source {
816 DerefSource::ImmRef => Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, fnty),
817 DerefSource::MutRef => Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, fnty),
818 DerefSource::MutPtr => Ty::new_mut_ptr(tcx, fnty),
819 },
820 Adjustment::RefMut => bug!("`RefMut` is never used with indirect calls: {shim:?}"),
821 };
822 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
823 }
824
825 if let ty::ShimKind::VTable(..) = shim {
828 let mut inputs_and_output = sig.inputs_and_output.to_vec();
830 let self_arg = &mut inputs_and_output[0];
831 debug_assert!(tcx.generics_of(def_id).has_self && *self_arg == tcx.types.self_param);
832 *self_arg = Ty::new_mut_ptr(tcx, *self_arg);
833 sig.inputs_and_output = tcx.mk_type_list(&inputs_and_output);
834 }
835
836 let span = tcx.def_span(def_id);
837
838 debug!(?sig);
839
840 let mut local_decls = local_decls_for_sig(&sig, span);
841 let source_info = SourceInfo::outermost(span);
842
843 let destination = Place::return_place();
844
845 let rcvr_place = || {
846 assert!(rcvr_adjustment.is_some());
847 Place::from(Local::arg(0))
848 };
849 let mut statements = vec![];
850
851 let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
852 Adjustment::Identity => Operand::Move(rcvr_place()),
853 Adjustment::Deref { source: _ } => Operand::Move(tcx.mk_place_deref(rcvr_place())),
854 Adjustment::RefMut => {
855 let ref_rcvr = local_decls.push(
857 LocalDecl::new(
858 Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, sig.inputs()[0]),
859 span,
860 )
861 .immutable(),
862 );
863 let borrow_kind = BorrowKind::Mut { kind: MutBorrowKind::Default };
864 statements.push(Statement::new(
865 source_info,
866 StatementKind::Assign(Box::new((
867 Place::from(ref_rcvr),
868 Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
869 ))),
870 ));
871 Operand::Move(Place::from(ref_rcvr))
872 }
873 });
874
875 let (callee, mut args) = match call_kind {
876 CallKind::Indirect(_) => (rcvr.unwrap(), vec![]),
878
879 CallKind::Direct(def_id) => {
881 let ty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
882 (
883 Operand::Constant(Box::new(ConstOperand {
884 span,
885 user_ty: None,
886 const_: Const::zero_sized(ty),
887 })),
888 rcvr.into_iter().collect::<Vec<_>>(),
889 )
890 }
891 };
892
893 let mut arg_range = 0..sig.inputs().len();
894
895 if rcvr_adjustment.is_some() {
897 arg_range.start += 1;
898 }
899
900 if untuple_args.is_some() {
902 arg_range.end -= 1;
903 }
904
905 args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::arg(i)))));
907
908 if let Some(untuple_args) = untuple_args {
910 let tuple_arg = Local::arg(sig.inputs().len() - 1);
911 args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
912 Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), FieldIdx::new(i), *ity))
913 }));
914 }
915
916 let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
917 let mut blocks = IndexVec::with_capacity(n_blocks);
918 let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
919 blocks.push(BasicBlockData::new_stmts(
920 statements,
921 Some(Terminator { source_info, kind, attributes: ThinVec::new() }),
922 is_cleanup,
923 ))
924 };
925
926 let args = args.into_iter().map(|a| Spanned { node: a, span: DUMMY_SP }).collect();
928 block(
929 &mut blocks,
930 statements,
931 TerminatorKind::Call {
932 func: callee,
933 args,
934 destination,
935 target: Some(BasicBlock::new(1)),
936 unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
937 UnwindAction::Cleanup(BasicBlock::new(3))
938 } else {
939 UnwindAction::Continue
940 },
941 call_source: CallSource::Misc,
942 fn_span: span,
943 },
944 false,
945 );
946
947 if let Some(Adjustment::RefMut) = rcvr_adjustment {
948 block(
950 &mut blocks,
951 vec![],
952 TerminatorKind::Drop {
953 place: rcvr_place(),
954 target: BasicBlock::new(2),
955 unwind: UnwindAction::Continue,
956 replace: false,
957 drop: None,
958 },
959 false,
960 );
961 }
962 let stmts = vec![];
964 block(&mut blocks, stmts, TerminatorKind::Return, false);
965 if let Some(Adjustment::RefMut) = rcvr_adjustment {
966 block(
968 &mut blocks,
969 vec![],
970 TerminatorKind::Drop {
971 place: rcvr_place(),
972 target: BasicBlock::new(4),
973 unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
974 replace: false,
975 drop: None,
976 },
977 true,
978 );
979
980 block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
982 }
983
984 let mut body =
985 new_body(MirSource::from_shim(shim), blocks, local_decls, sig.inputs().len(), span);
986
987 if let ExternAbi::RustCall = sig.abi() {
988 body.spread_arg = Some(Local::new(sig.inputs().len()));
989 }
990
991 body
992}
993
994pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
995 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));
996
997 let typing_env = ty::TypingEnv::post_analysis(tcx, ctor_id);
998
999 let sig = tcx
1001 .fn_sig(ctor_id)
1002 .instantiate_identity()
1003 .skip_norm_wip()
1004 .no_bound_vars()
1005 .expect("LBR in ADT constructor signature");
1006 let sig = tcx.normalize_erasing_regions(typing_env, Unnormalized::new_wip(sig));
1007
1008 let ty::Adt(adt_def, args) = sig.output().kind() else {
1009 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type for ADT ctor {0:?}",
sig.output()));bug!("unexpected type for ADT ctor {:?}", sig.output());
1010 };
1011
1012 {
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:1012",
"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(1012u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("build_ctor: ctor_id={0:?} sig={1:?}",
ctor_id, sig) as &dyn Value))])
});
} else { ; }
};debug!("build_ctor: ctor_id={:?} sig={:?}", ctor_id, sig);
1013
1014 let span = tcx.def_span(ctor_id);
1015
1016 let local_decls = local_decls_for_sig(&sig, span);
1017
1018 let source_info = SourceInfo::outermost(span);
1019
1020 let variant_index =
1021 if adt_def.is_enum() { adt_def.variant_index_with_ctor_id(ctor_id) } else { FIRST_VARIANT };
1022
1023 {
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:1029",
"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(1029u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("build_ctor: variant_index={0:?}",
variant_index) as &dyn Value))])
});
} else { ; }
};debug!("build_ctor: variant_index={:?}", variant_index);
1030
1031 let kind = AggregateKind::Adt(adt_def.did(), variant_index, args, None, None);
1032 let variant = adt_def.variant(variant_index);
1033 let statement = Statement::new(
1034 source_info,
1035 StatementKind::Assign(Box::new((
1036 Place::return_place(),
1037 Rvalue::Aggregate(
1038 Box::new(kind),
1039 (0..variant.fields.len())
1040 .map(|idx| Operand::Move(Place::from(Local::arg(idx))))
1041 .collect(),
1042 ),
1043 ))),
1044 );
1045
1046 let start_block = BasicBlockData::new_stmts(
1047 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[statement]))vec![statement],
1048 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1049 false,
1050 );
1051
1052 let source = MirSource::item(ctor_id);
1053 let mut body = new_body(
1054 source,
1055 IndexVec::from_elem_n(start_block, 1),
1056 local_decls,
1057 sig.inputs().len(),
1058 span,
1059 );
1060 body.set_mentioned_items(Vec::new());
1063
1064 pm::run_passes_no_validate(
1065 tcx,
1066 &mut body,
1067 &[],
1068 Some(MirPhase::Runtime(RuntimePhase::Optimized)),
1069 );
1070
1071 body
1072}
1073
1074fn build_fn_ptr_addr_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> {
1082 {
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}");
1083 let span = tcx.def_span(def_id);
1084 let Some(sig) =
1085 tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).skip_norm_wip().no_bound_vars()
1086 else {
1087 ::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}`");
1088 };
1089 let locals = local_decls_for_sig(&sig, span);
1090
1091 let source_info = SourceInfo::outermost(span);
1092 let rvalue = Rvalue::Cast(
1095 CastKind::FnPtrToPtr,
1096 Operand::Move(Place::from(Local::arg(0))),
1097 Ty::new_imm_ptr(tcx, tcx.types.unit),
1098 );
1099 let stmt = Statement::new(
1100 source_info,
1101 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1102 );
1103 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1104 let start_block = BasicBlockData::new_stmts(
1105 statements,
1106 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1107 false,
1108 );
1109 let source = MirSource::from_shim(ty::ShimKind::FnPtrAddr(def_id, self_ty));
1110 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span)
1111}
1112
1113fn build_construct_coroutine_by_move_shim<'tcx>(
1114 tcx: TyCtxt<'tcx>,
1115 coroutine_closure_def_id: DefId,
1116 receiver_by_ref: bool,
1117) -> Body<'tcx> {
1118 let mut self_ty = tcx.type_of(coroutine_closure_def_id).instantiate_identity().skip_norm_wip();
1119 let mut self_local: Place<'tcx> = Local::arg(0).into();
1120 let ty::CoroutineClosure(_, args) = *self_ty.kind() else {
1121 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1122 };
1123
1124 if receiver_by_ref {
1130 self_local = tcx.mk_place_deref(self_local);
1131 self_ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, self_ty);
1132 }
1133
1134 let poly_sig = args.as_coroutine_closure().coroutine_closure_sig().map_bound(|sig| {
1135 tcx.mk_fn_sig(
1136 [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()),
1137 sig.to_coroutine_given_kind_and_upvars(
1138 tcx,
1139 args.as_coroutine_closure().parent_args(),
1140 tcx.coroutine_for_closure(coroutine_closure_def_id),
1141 ty::ClosureKind::FnOnce,
1142 tcx.lifetimes.re_erased,
1143 args.as_coroutine_closure().tupled_upvars_ty(),
1144 args.as_coroutine_closure().coroutine_captures_by_ref_ty(),
1145 ),
1146 sig.fn_sig_kind,
1147 )
1148 });
1149 let sig = tcx.liberate_late_bound_regions(coroutine_closure_def_id, poly_sig);
1150 let ty::Coroutine(coroutine_def_id, coroutine_args) = *sig.output().kind() else {
1151 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"));bug!();
1152 };
1153
1154 let span = tcx.def_span(coroutine_closure_def_id);
1155 let locals = local_decls_for_sig(&sig, span);
1156
1157 let mut fields = ::alloc::vec::Vec::new()vec![];
1158
1159 for idx in 1..sig.inputs().len() {
1161 fields.push(Operand::Move(Local::arg(idx).into()));
1162 }
1163
1164 for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
1165 if receiver_by_ref {
1166 if !#[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Ref(_, _, hir::Mutability::Not) => true,
_ => false,
}matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
1170 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!(
1174 "field should be captured by immutable ref if we have \
1175 an `Fn` instance, but it was: {ty}"
1176 ));
1177 }
1178 fields.push(Operand::Copy(tcx.mk_place_field(
1179 self_local,
1180 FieldIdx::from_usize(idx),
1181 ty,
1182 )));
1183 } else {
1184 fields.push(Operand::Move(tcx.mk_place_field(
1185 self_local,
1186 FieldIdx::from_usize(idx),
1187 ty,
1188 )));
1189 }
1190 }
1191
1192 let source_info = SourceInfo::outermost(span);
1193 let rvalue = Rvalue::Aggregate(
1194 Box::new(AggregateKind::Coroutine(coroutine_def_id, coroutine_args)),
1195 IndexVec::from_raw(fields),
1196 );
1197 let stmt = Statement::new(
1198 source_info,
1199 StatementKind::Assign(Box::new((Place::return_place(), rvalue))),
1200 );
1201 let statements = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[stmt]))vec![stmt];
1202 let start_block = BasicBlockData::new_stmts(
1203 statements,
1204 Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }),
1205 false,
1206 );
1207
1208 let source = MirSource::from_shim(ty::ShimKind::ConstructCoroutineInClosure {
1209 coroutine_closure_def_id,
1210 receiver_by_ref,
1211 });
1212
1213 let body =
1214 new_body(source, IndexVec::from_elem_n(start_block, 1), locals, sig.inputs().len(), span);
1215
1216 let pass_name =
1217 if receiver_by_ref { "coroutine_closure_by_ref" } else { "coroutine_closure_by_move" };
1218 if let Some(dumper) = MirDumper::new(tcx, pass_name, &body) {
1219 dumper.dump_mir(&body);
1220 }
1221
1222 body
1223}