1use rustc_attr_ir::lang_items::LangItem;
2use rustc_hir::def_id::DefId;
3use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource};
4use rustc_index::{Idx, IndexVec};
5use rustc_middle::mir::{
6 BasicBlock, BasicBlockData, Body, Local, LocalDecl, MirSource, Operand, Place, Rvalue,
7 SourceInfo, Statement, StatementKind, Terminator, TerminatorKind,
8};
9use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitableExt};
10
11use super::*;
12use crate::deref_separator::deref_finder;
13use crate::patch::MirPatch;
14
15const SELF_ARG: Local = Local::arg(0);
16
17pub(super) fn build_async_destructor_ctor_shim<'tcx>(
18 tcx: TyCtxt<'tcx>,
19 def_id: DefId,
20 ty: Ty<'tcx>,
21) -> Body<'tcx> {
22 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs:22",
"rustc_mir_transform::shim::async_destructor_ctor",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs"),
::tracing_core::__macro_support::Option::Some(22u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim::async_destructor_ctor"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("build_async_destructor_ctor_shim(def_id={0:?}, ty={1:?})",
def_id, ty) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("build_async_destructor_ctor_shim(def_id={:?}, ty={:?})", def_id, ty);
23 if true {
{
match (&Some(def_id), &tcx.lang_items().async_drop_in_place_fn()) {
(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);
}
}
}
};
};debug_assert_eq!(Some(def_id), tcx.lang_items().async_drop_in_place_fn());
24 let generic_body = tcx.optimized_mir(def_id);
25 let args = tcx.mk_args(&[ty.into()]);
26 let mut body =
27 EarlyBinder::bind(tcx, generic_body.clone()).instantiate(tcx, args).skip_norm_wip();
28
29 pm::run_passes(
32 tcx,
33 &mut body,
34 &[
35 &simplify::SimplifyCfg::MakeShim,
36 &abort_unwinding_calls::AbortUnwindingCalls,
37 &add_call_guards::CriticalCallEdges,
38 ],
39 None,
40 );
41 body
42}
43
44{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() || { false }
{
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("build_async_drop_shim",
"rustc_mir_transform::shim::async_destructor_ctor",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs"),
::tracing_core::__macro_support::Option::Some(45u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim::async_destructor_ctor"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Body<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let ty::Coroutine(_, parent_args) =
ty.kind() else {
::rustc_span::macros::bug_impl(None,
format_args!("impossible case reached"),
Location::caller());
};
let typing_env = ty::TypingEnv::fully_monomorphized();
let drop_ty = parent_args.first().unwrap().expect_ty();
let drop_ptr_ty =
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty);
if !tcx.is_coroutine(def_id) {
::core::panicking::panic("assertion failed: tcx.is_coroutine(def_id)")
};
let coroutine_kind = tcx.coroutine_kind(def_id).unwrap();
if !#[allow(non_exhaustive_omitted_patterns)] match coroutine_kind
{
CoroutineKind::Desugared(CoroutineDesugaring::Async,
CoroutineSource::Fn) => true,
_ => false,
} {
::core::panicking::panic("assertion failed: matches!(coroutine_kind,\n CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn))")
};
let needs_async_drop =
drop_ty.needs_async_drop(tcx, typing_env);
let needs_sync_drop =
!needs_async_drop && drop_ty.needs_drop(tcx, typing_env);
let resume_adt =
tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy,
DUMMY_SP));
let resume_ty =
Ty::new_adt(tcx, resume_adt, ty::GenericArgs::empty());
let fn_sig =
ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([ty,
resume_ty], tcx.types.unit));
let sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
if !!drop_ty.is_coroutine() {
::core::panicking::panic("assertion failed: !drop_ty.is_coroutine()")
};
let span = tcx.def_span(def_id);
let source_info = SourceInfo::outermost(span);
let coroutine_layout = Place::from(SELF_ARG);
let coroutine_layout_dropee =
tcx.mk_place_field(coroutine_layout, FieldIdx::new(0),
drop_ptr_ty);
let return_block = BasicBlock::new(1);
let mut blocks = IndexVec::with_capacity(2);
let block =
|blocks: &mut IndexVec<_, _>, kind| -> BasicBlock
{
blocks.push(BasicBlockData::new(Terminator {
source_info,
kind,
}, false))
};
block(&mut blocks,
if needs_sync_drop {
TerminatorKind::Drop {
place: tcx.mk_place_deref(coroutine_layout_dropee),
target: return_block,
unwind: UnwindAction::Continue,
replace: false,
drop: None,
}
} else { TerminatorKind::goto(return_block) });
let ret = block(&mut blocks, TerminatorKind::Return);
blocks[ret].statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((Place::return_place(),
Rvalue::Use(Operand::zero_sized_constant(tcx.types.unit,
span), WithRetag::Yes))))));
let source =
MirSource::from_shim(ty::ShimKind::AsyncDropGlue(def_id,
ty));
let mut body =
new_body(source, blocks, local_decls_for_sig(&sig, span),
sig.inputs().len(), span);
body.coroutine =
Some(Box::new(CoroutineInfo::initial(coroutine_kind,
parent_args.as_coroutine().yield_ty(),
parent_args.as_coroutine().resume_ty())));
body.phase = MirPhase::Runtime(RuntimePhase::Initial);
if needs_async_drop && !drop_ty.references_error() {
let dropee_ptr =
Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty,
span)));
let st_kind =
StatementKind::Assign(Box::new((dropee_ptr,
Rvalue::Use(Operand::Move(coroutine_layout_dropee),
WithRetag::Yes))));
body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info,
st_kind));
let dropline = body.basic_blocks.last_index();
let patch =
{
let mut elaborator =
DropShimElaborator {
body: &body,
patch: MirPatch::new(&body),
tcx,
typing_env,
produce_async_drops: true,
};
let dropee = tcx.mk_place_deref(dropee_ptr);
let resume_block = elaborator.patch.resume_block();
elaborate_drop(&mut elaborator, source_info, dropee, (),
return_block, Unwind::To(resume_block), START_BLOCK,
dropline);
elaborator.patch
};
patch.apply(&mut body);
}
deref_finder(tcx, &mut body, false);
body
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs:45",
"rustc_mir_transform::shim::async_destructor_ctor",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5b7b37aefcb5b2fba3c2392bc9065b9e4602d494/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs"),
::tracing_core::__macro_support::Option::Some(45u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::shim::async_destructor_ctor"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[tracing::instrument(level = "trace", skip(tcx), ret)]
46pub(super) fn build_async_drop_shim<'tcx>(
47 tcx: TyCtxt<'tcx>,
48 def_id: DefId,
49 ty: Ty<'tcx>,
50) -> Body<'tcx> {
51 let ty::Coroutine(_, parent_args) = ty.kind() else {
52 bug!();
53 };
54 let typing_env = ty::TypingEnv::fully_monomorphized();
55
56 let drop_ty = parent_args.first().unwrap().expect_ty();
57 let drop_ptr_ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, drop_ty);
58
59 assert!(tcx.is_coroutine(def_id));
60 let coroutine_kind = tcx.coroutine_kind(def_id).unwrap();
61
62 assert!(matches!(
63 coroutine_kind,
64 CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Fn)
65 ));
66
67 let needs_async_drop = drop_ty.needs_async_drop(tcx, typing_env);
68 let needs_sync_drop = !needs_async_drop && drop_ty.needs_drop(tcx, typing_env);
69
70 let resume_adt = tcx.adt_def(tcx.require_lang_item(LangItem::ResumeTy, DUMMY_SP));
71 let resume_ty = Ty::new_adt(tcx, resume_adt, ty::GenericArgs::empty());
72
73 let fn_sig = ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi([ty, resume_ty], tcx.types.unit));
74 let sig = tcx.instantiate_bound_regions_with_erased(fn_sig);
75
76 assert!(!drop_ty.is_coroutine());
77 let span = tcx.def_span(def_id);
78 let source_info = SourceInfo::outermost(span);
79
80 let coroutine_layout = Place::from(SELF_ARG);
82 let coroutine_layout_dropee =
83 tcx.mk_place_field(coroutine_layout, FieldIdx::new(0), drop_ptr_ty);
84
85 let return_block = BasicBlock::new(1);
86 let mut blocks = IndexVec::with_capacity(2);
87 let block = |blocks: &mut IndexVec<_, _>, kind| -> BasicBlock {
88 blocks.push(BasicBlockData::new(Terminator { source_info, kind }, false))
89 };
90 block(
91 &mut blocks,
92 if needs_sync_drop {
93 TerminatorKind::Drop {
94 place: tcx.mk_place_deref(coroutine_layout_dropee),
95 target: return_block,
96 unwind: UnwindAction::Continue,
97 replace: false,
98 drop: None,
99 }
100 } else {
101 TerminatorKind::goto(return_block)
102 },
103 );
104 let ret = block(&mut blocks, TerminatorKind::Return);
105 blocks[ret].statements.push(Statement::new(
106 source_info,
107 StatementKind::Assign(Box::new((
108 Place::return_place(),
109 Rvalue::Use(Operand::zero_sized_constant(tcx.types.unit, span), WithRetag::Yes),
110 ))),
111 ));
112
113 let source = MirSource::from_shim(ty::ShimKind::AsyncDropGlue(def_id, ty));
114 let mut body =
115 new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
116
117 body.coroutine = Some(Box::new(CoroutineInfo::initial(
118 coroutine_kind,
119 parent_args.as_coroutine().yield_ty(),
120 parent_args.as_coroutine().resume_ty(),
121 )));
122 body.phase = MirPhase::Runtime(RuntimePhase::Initial);
123
124 if needs_async_drop && !drop_ty.references_error() {
128 let dropee_ptr = Place::from(body.local_decls.push(LocalDecl::new(drop_ptr_ty, span)));
129 let st_kind = StatementKind::Assign(Box::new((
130 dropee_ptr,
131 Rvalue::Use(Operand::Move(coroutine_layout_dropee), WithRetag::Yes),
132 )));
133 body.basic_blocks_mut()[START_BLOCK].statements.push(Statement::new(source_info, st_kind));
134
135 let dropline = body.basic_blocks.last_index();
136
137 let patch = {
138 let mut elaborator = DropShimElaborator {
139 body: &body,
140 patch: MirPatch::new(&body),
141 tcx,
142 typing_env,
143 produce_async_drops: true,
144 };
145 let dropee = tcx.mk_place_deref(dropee_ptr);
146 let resume_block = elaborator.patch.resume_block();
147 elaborate_drop(
148 &mut elaborator,
149 source_info,
150 dropee,
151 (),
152 return_block,
153 Unwind::To(resume_block),
154 START_BLOCK,
155 dropline,
156 );
157 elaborator.patch
158 };
159 patch.apply(&mut body);
160 }
161
162 deref_finder(tcx, &mut body, false);
164
165 body
166}
167
168pub(super) fn build_future_drop_poll_shim<'tcx>(
177 tcx: TyCtxt<'tcx>,
178 def_id: DefId,
179 proxy_ty: Ty<'tcx>,
180 impl_ty: Ty<'tcx>,
181) -> Body<'tcx> {
182 let shim = ty::ShimKind::FutureDropPoll(def_id, proxy_ty, impl_ty);
183 let ty::Coroutine(coroutine_def_id, _) = impl_ty.kind() else {
184 ::rustc_span::macros::bug_impl(None,
format_args!("build_future_drop_poll_shim not for coroutine impl type: ({0:?})",
shim), Location::caller());bug!("build_future_drop_poll_shim not for coroutine impl type: ({:?})", shim);
185 };
186
187 let span = tcx.def_span(def_id);
188
189 if tcx.is_async_drop_in_place_coroutine(*coroutine_def_id) {
190 build_adrop_for_adrop_shim(tcx, proxy_ty, impl_ty, span, shim)
191 } else {
192 build_adrop_for_coroutine_shim(tcx, proxy_ty, impl_ty, span, shim)
193 }
194}
195
196fn build_adrop_for_coroutine_shim<'tcx>(
201 tcx: TyCtxt<'tcx>,
202 proxy_ty: Ty<'tcx>,
203 impl_ty: Ty<'tcx>,
204 span: Span,
205 shim: ty::ShimKind<'tcx>,
206) -> Body<'tcx> {
207 let ty::Coroutine(coroutine_def_id, impl_args) = impl_ty.kind() else {
208 ::rustc_span::macros::bug_impl(None,
format_args!("build_adrop_for_coroutine_shim not for coroutine impl type: ({0:?})",
shim), Location::caller());bug!("build_adrop_for_coroutine_shim not for coroutine impl type: ({:?})", shim);
209 };
210 let ty::Coroutine(_, id_args) = *tcx.type_of(*coroutine_def_id).skip_binder().kind() else {
211 ::rustc_span::macros::bug_impl(None, format_args!("impossible case reached"),
Location::caller())bug!()
212 };
213 let source_info = SourceInfo::outermost(span);
214
215 let def_id = if id_args.as_coroutine().kind_ty() == impl_args.as_coroutine().kind_ty() {
217 *coroutine_def_id
218 } else {
219 {
match (&impl_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!(
220 impl_args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap(),
221 ty::ClosureKind::FnOnce
222 );
223
224 tcx.coroutine_by_move_body_def_id(*coroutine_def_id)
225 };
226 let body = tcx.optimized_mir(def_id).future_drop_poll().unwrap();
227 let mut body: Body<'tcx> =
228 EarlyBinder::bind(tcx, body.clone()).instantiate(tcx, impl_args).skip_norm_wip();
229 body.source.instance = ty::InstanceKind::Shim(shim);
230 body.phase = MirPhase::Runtime(RuntimePhase::Initial);
231 body.var_debug_info.clear();
232
233 let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty);
238
239 let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
240 let args = tcx.mk_args(&[proxy_ref.into()]);
241 let pin_proxy_ref = Ty::new_adt(tcx, pin_adt_ref, args);
242
243 let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty);
244 let cor_ref_local = body.local_decls.push(LocalDecl::new(cor_ref, span));
245
246 FixProxyFutureDropVisitor { tcx, replace_to: cor_ref_local }.visit_body(&mut body);
247
248 body.local_decls[SELF_ARG] = LocalDecl::new(pin_proxy_ref, span);
250
251 let mut pin_proxy_to_cor_projection = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)]))vec![
253 PlaceElem::Field(FieldIdx::ZERO, proxy_ref),
255 ];
256
257 proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| {
259 if ty != proxy_ty {
260 let ty_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
261 pin_proxy_to_cor_projection.push(PlaceElem::Deref);
262 pin_proxy_to_cor_projection.push(PlaceElem::Field(FieldIdx::ZERO, ty_ref));
263 }
264 });
265
266 let projected_pin = Place::from(SELF_ARG).project_deeper(&pin_proxy_to_cor_projection, tcx);
268 body.basic_blocks_mut()[START_BLOCK].statements.insert(
269 0,
270 Statement::new(
271 source_info,
272 StatementKind::Assign(Box::new((
273 Place::from(cor_ref_local),
274 Rvalue::Use(Operand::Move(projected_pin), WithRetag::Yes),
275 ))),
276 ),
277 );
278
279 deref_finder(tcx, &mut body, false);
281
282 return body;
283
284 struct FixProxyFutureDropVisitor<'tcx> {
286 tcx: TyCtxt<'tcx>,
287 replace_to: Local,
288 }
289
290 impl<'tcx> MutVisitor<'tcx> for FixProxyFutureDropVisitor<'tcx> {
291 fn tcx(&self) -> TyCtxt<'tcx> {
292 self.tcx
293 }
294
295 fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext, _: Location) {
296 if place.local == SELF_ARG
297 && let Some((first, rest)) = place.projection.split_first()
298 {
299 if !#[allow(non_exhaustive_omitted_patterns)] match first {
ProjectionElem::Field(FieldIdx::ZERO, _) => true,
_ => false,
} {
::core::panicking::panic("assertion failed: matches!(first, ProjectionElem::Field(FieldIdx::ZERO, _))")
};assert!(matches!(first, ProjectionElem::Field(FieldIdx::ZERO, _)));
300 *place = Place::from(self.replace_to).project_deeper(rest, self.tcx);
301 }
302 }
303 }
304}
305
306fn build_adrop_for_adrop_shim<'tcx>(
309 tcx: TyCtxt<'tcx>,
310 proxy_ty: Ty<'tcx>,
311 impl_ty: Ty<'tcx>,
312 span: Span,
313 shim: ty::ShimKind<'tcx>,
314) -> Body<'tcx> {
315 let source_info = SourceInfo::outermost(span);
316 let proxy_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, proxy_ty);
317 let proxy_ref_place =
319 Place::from(SELF_ARG).project_deeper(&[PlaceElem::Field(FieldIdx::ZERO, proxy_ref)], tcx);
320 let cor_ref = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, impl_ty);
321
322 let poll_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Poll, span));
324 let ret_ty = Ty::new_adt(tcx, poll_adt_ref, tcx.mk_args(&[tcx.types.unit.into()]));
325 let pin_adt_ref = tcx.adt_def(tcx.require_lang_item(LangItem::Pin, span));
327 let env_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[proxy_ref.into()]));
328 let sig = tcx.mk_fn_sig_safe_rust_abi([env_ty, Ty::new_task_context(tcx)], ret_ty);
330 let mut locals = local_decls_for_sig(&sig, span);
334 let mut blocks = IndexVec::with_capacity(3);
335
336 let proxy_ref_local = locals.push(LocalDecl::new(proxy_ref, span));
337
338 let call_bb = BasicBlock::new(1);
339 let return_bb = BasicBlock::new(2);
340
341 let mut statements = Vec::new();
342
343 statements.push(Statement::new(
344 source_info,
345 StatementKind::Assign(Box::new((
346 Place::from(proxy_ref_local),
347 Rvalue::Use(Operand::Copy(proxy_ref_place), WithRetag::Yes),
348 ))),
349 ));
350
351 let mut cor_ptr_local = proxy_ref_local;
352 proxy_ty.find_async_drop_impl_coroutine(tcx, |ty| {
353 if ty != proxy_ty {
354 let ty_ptr = Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, ty);
355 let impl_ptr_place = Place::from(cor_ptr_local)
356 .project_deeper(&[PlaceElem::Deref, PlaceElem::Field(FieldIdx::ZERO, ty_ptr)], tcx);
357 cor_ptr_local = locals.push(LocalDecl::new(ty_ptr, span));
358 statements.push(Statement::new(
360 source_info,
361 StatementKind::Assign(Box::new((
362 Place::from(cor_ptr_local),
363 Rvalue::Use(Operand::Copy(impl_ptr_place), WithRetag::Yes),
364 ))),
365 ));
366 }
367 });
368
369 let reborrow = Rvalue::Ref(
371 tcx.lifetimes.re_erased,
372 BorrowKind::Mut { kind: MutBorrowKind::Default },
373 tcx.mk_place_deref(Place::from(cor_ptr_local)),
374 );
375 let cor_ref_place = Place::from(locals.push(LocalDecl::new(cor_ref, span)));
376 statements.push(Statement::new(
377 source_info,
378 StatementKind::Assign(Box::new((cor_ref_place, reborrow))),
379 ));
380
381 let cor_pin_ty = Ty::new_adt(tcx, pin_adt_ref, tcx.mk_args(&[cor_ref.into()]));
383 let cor_pin_place = Place::from(locals.push(LocalDecl::new(cor_pin_ty, span)));
384
385 let pin_fn = tcx.require_lang_item(LangItem::PinNewUnchecked, span);
386 blocks.push(BasicBlockData::new_stmts(
388 statements,
389 Terminator {
390 source_info,
391 kind: TerminatorKind::Call {
392 func: Operand::function_handle(tcx, pin_fn, &[cor_ref.into()], span),
393 args: [dummy_spanned(Operand::Move(cor_ref_place))].into(),
394 destination: cor_pin_place,
395 target: Some(call_bb),
396 unwind: UnwindAction::Continue,
397 call_source: CallSource::Misc,
398 fn_span: span,
399 },
400 },
401 false,
402 ));
403 let poll_fn = tcx.require_lang_item(LangItem::FuturePoll, span);
406 let resume_ctx = Place::from(Local::new(2));
407 blocks.push(BasicBlockData::new(
408 Terminator {
409 source_info,
410 kind: TerminatorKind::Call {
411 func: Operand::function_handle(tcx, poll_fn, &[impl_ty.into()], span),
412 args: [
413 dummy_spanned(Operand::Move(cor_pin_place)),
414 dummy_spanned(Operand::Move(resume_ctx)),
415 ]
416 .into(),
417 destination: Place::return_place(),
418 target: Some(return_bb),
419 unwind: UnwindAction::Continue,
420 call_source: CallSource::Misc,
421 fn_span: span,
422 },
423 },
424 false,
425 ));
426 blocks
427 .push(BasicBlockData::new(Terminator { source_info, kind: TerminatorKind::Return }, false));
428
429 let source = MirSource::from_shim(shim);
430 let mut body = new_body(source, blocks, locals, sig.inputs().len(), span);
431 body.phase = MirPhase::Runtime(RuntimePhase::Initial);
432 return body;
433}