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