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