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