Skip to content

Commit 567b4a2

Browse files
committed
AsyncDrop implementation using shim codegen of async_drop_in_place::{closure}, scoped async drop added.
1 parent 1de9312 commit 567b4a2

File tree

118 files changed

+4225
-1876
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

118 files changed

+4225
-1876
lines changed

compiler/rustc_borrowck/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,14 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
659659
TerminatorKind::SwitchInt { discr, targets: _ } => {
660660
self.consume_operand(loc, (discr, span), state);
661661
}
662-
TerminatorKind::Drop { place, target: _, unwind: _, replace } => {
662+
TerminatorKind::Drop {
663+
place,
664+
target: _,
665+
unwind: _,
666+
replace,
667+
drop: _,
668+
async_fut: _,
669+
} => {
663670
debug!(
664671
"visit_terminator_drop \
665672
loc: {:?} term: {:?} place: {:?} span: {:?}",

compiler/rustc_borrowck/src/polonius/legacy/loan_invalidations.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,14 @@ impl<'a, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'a, 'tcx> {
101101
TerminatorKind::SwitchInt { discr, targets: _ } => {
102102
self.consume_operand(location, discr);
103103
}
104-
TerminatorKind::Drop { place: drop_place, target: _, unwind: _, replace } => {
104+
TerminatorKind::Drop {
105+
place: drop_place,
106+
target: _,
107+
unwind: _,
108+
replace,
109+
drop: _,
110+
async_fut: _,
111+
} => {
105112
let write_kind =
106113
if *replace { WriteKind::Replace } else { WriteKind::StorageDeadOrDrop };
107114
self.access_place(

compiler/rustc_borrowck/src/type_check/mod.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -2086,8 +2086,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20862086
}
20872087
}
20882088
TerminatorKind::Unreachable => {}
2089-
TerminatorKind::Drop { target, unwind, .. }
2090-
| TerminatorKind::Assert { target, unwind, .. } => {
2089+
TerminatorKind::Drop { target, unwind, drop, .. } => {
2090+
self.assert_iscleanup(block_data, target, is_cleanup);
2091+
self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
2092+
if let Some(drop) = drop {
2093+
self.assert_iscleanup(block_data, drop, is_cleanup);
2094+
}
2095+
}
2096+
TerminatorKind::Assert { target, unwind, .. } => {
20912097
self.assert_iscleanup(block_data, target, is_cleanup);
20922098
self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
20932099
}

compiler/rustc_codegen_cranelift/src/abi/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,9 @@ pub(crate) fn codegen_terminator_call<'tcx>(
441441
Err(instance) => Some(instance),
442442
}
443443
}
444-
InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) => {
444+
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
445+
// it is `func returning noop future`
446+
InstanceKind::DropGlue(_, None) => {
445447
// empty drop glue - a nop.
446448
let dest = target.expect("Non terminating drop_in_place_real???");
447449
let ret_block = fx.get_block(dest);
@@ -707,9 +709,8 @@ pub(crate) fn codegen_drop<'tcx>(
707709
let ty = drop_place.layout().ty;
708710
let drop_instance = Instance::resolve_drop_in_place(fx.tcx, ty);
709711

710-
if let ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None) =
711-
drop_instance.def
712-
{
712+
// AsyncDropGlueCtorShim can't be here
713+
if let ty::InstanceKind::DropGlue(_, None) = drop_instance.def {
713714
// we don't actually need to drop anything
714715
} else {
715716
match ty.kind() {

compiler/rustc_codegen_cranelift/src/base.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,11 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
565565
| TerminatorKind::CoroutineDrop => {
566566
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
567567
}
568-
TerminatorKind::Drop { place, target, unwind: _, replace: _ } => {
568+
TerminatorKind::Drop { place, target, unwind: _, replace: _, drop, async_fut } => {
569+
assert!(
570+
async_fut.is_none() && drop.is_none(),
571+
"Async Drop must be expanded or reset to sync before codegen"
572+
);
569573
let drop_place = codegen_place(fx, *place);
570574
crate::abi::codegen_drop(fx, source_info, drop_place, *target);
571575
}

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -721,8 +721,7 @@ fn build_union_fields_for_direct_tag_coroutine<'ll, 'tcx>(
721721
_ => unreachable!(),
722722
};
723723

724-
let coroutine_layout =
725-
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.kind_ty()).unwrap();
724+
let coroutine_layout = cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args.args).unwrap();
726725

727726
let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(coroutine_def_id);
728727
let variant_range = coroutine_args.variant_range(coroutine_def_id, cx.tcx);

compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,8 @@ pub(super) fn build_coroutine_di_node<'ll, 'tcx>(
174174
DIFlags::FlagZero,
175175
),
176176
|cx, coroutine_type_di_node| {
177-
let coroutine_layout = cx
178-
.tcx
179-
.coroutine_layout(coroutine_def_id, coroutine_args.as_coroutine().kind_ty())
180-
.unwrap();
177+
let coroutine_layout =
178+
cx.tcx.coroutine_layout(coroutine_def_id, coroutine_args).unwrap();
181179

182180
let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } =
183181
coroutine_type_and_layout.variants

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ fn exported_symbols_provider_local(
374374
));
375375
}
376376
MonoItem::Fn(Instance {
377-
def: InstanceKind::AsyncDropGlueCtorShim(_, Some(ty)),
377+
def: InstanceKind::AsyncDropGlueCtorShim(_, ty),
378378
args,
379379
}) => {
380380
// A little sanity-check
@@ -388,6 +388,16 @@ fn exported_symbols_provider_local(
388388
},
389389
));
390390
}
391+
MonoItem::Fn(Instance { def: InstanceKind::AsyncDropGlue(_, ty), args: _ }) => {
392+
symbols.push((
393+
ExportedSymbol::AsyncDropGlue(ty),
394+
SymbolExportInfo {
395+
level: SymbolExportLevel::Rust,
396+
kind: SymbolExportKind::Text,
397+
used: false,
398+
},
399+
));
400+
}
391401
_ => {
392402
// Any other symbols don't qualify for sharing
393403
}
@@ -411,6 +421,7 @@ fn upstream_monomorphizations_provider(
411421

412422
let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
413423
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
424+
let async_drop_in_place_poll_fn_def_id = tcx.lang_items().async_drop_in_place_poll_fn();
414425

415426
for &cnum in cnums.iter() {
416427
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
@@ -429,8 +440,13 @@ fn upstream_monomorphizations_provider(
429440
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
430441
(async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
431442
} else {
432-
// `drop_in_place` in place does not exist, don't try
433-
// to use it.
443+
continue;
444+
}
445+
}
446+
ExportedSymbol::AsyncDropGlue(ty) => {
447+
if let Some(poll_fn_def_id) = async_drop_in_place_poll_fn_def_id {
448+
(poll_fn_def_id, tcx.mk_args(&[ty.into()]))
449+
} else {
434450
continue;
435451
}
436452
}
@@ -582,6 +598,13 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
582598
instantiating_crate,
583599
)
584600
}
601+
ExportedSymbol::AsyncDropGlue(ty) => {
602+
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
603+
tcx,
604+
Instance::resolve_async_drop_in_place_poll(tcx, ty),
605+
instantiating_crate,
606+
)
607+
}
585608
ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
586609
}
587610
}
@@ -604,6 +627,7 @@ fn calling_convention_for_symbol<'tcx>(
604627
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
605628
// target's default symbol decoration scheme.
606629
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
630+
ExportedSymbol::AsyncDropGlue(..) => None,
607631
// NoDefId always follow the target's default symbol decoration scheme.
608632
ExportedSymbol::NoDefId(..) => None,
609633
// ThreadLocalShim always follow the target's default symbol decoration scheme.

compiler/rustc_codegen_ssa/src/mir/block.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -926,10 +926,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
926926

927927
let def = instance.map(|i| i.def);
928928

929-
if let Some(
930-
ty::InstanceKind::DropGlue(_, None) | ty::InstanceKind::AsyncDropGlueCtorShim(_, None),
931-
) = def
932-
{
929+
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
930+
// it is `func returning noop future`
931+
if let Some(ty::InstanceKind::DropGlue(_, None)) = def {
933932
// Empty drop glue; a no-op.
934933
let target = target.unwrap();
935934
return helper.funclet_br(self, bx, target, mergeable_succ);
@@ -1386,16 +1385,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13861385
MergingSucc::False
13871386
}
13881387

1389-
mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
1390-
.codegen_drop_terminator(
1388+
mir::TerminatorKind::Drop { place, target, unwind, replace: _, drop, async_fut } => {
1389+
assert!(
1390+
async_fut.is_none() && drop.is_none(),
1391+
"Async Drop must be expanded or reset to sync before codegen"
1392+
);
1393+
self.codegen_drop_terminator(
13911394
helper,
13921395
bx,
13931396
&terminator.source_info,
13941397
place,
13951398
target,
13961399
unwind,
13971400
mergeable_succ(),
1398-
),
1401+
)
1402+
}
13991403

14001404
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
14011405
.codegen_assert_terminator(

compiler/rustc_const_eval/src/const_eval/machine.rs

+1
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
502502
RemainderByZero(op) => RemainderByZero(eval_to_int(op)?),
503503
ResumedAfterReturn(coroutine_kind) => ResumedAfterReturn(*coroutine_kind),
504504
ResumedAfterPanic(coroutine_kind) => ResumedAfterPanic(*coroutine_kind),
505+
ResumedAfterDrop(coroutine_kind) => ResumedAfterDrop(*coroutine_kind),
505506
MisalignedPointerDereference { required, found } => MisalignedPointerDereference {
506507
required: eval_to_int(required)?,
507508
found: eval_to_int(found)?,

compiler/rustc_const_eval/src/interpret/call.rs

+2
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
570570
| ty::InstanceKind::FnPtrAddrShim(..)
571571
| ty::InstanceKind::ThreadLocalShim(..)
572572
| ty::InstanceKind::AsyncDropGlueCtorShim(..)
573+
| ty::InstanceKind::AsyncDropGlue(..)
574+
| ty::InstanceKind::FutureDropPollShim(..)
573575
| ty::InstanceKind::Item(_) => {
574576
// We need MIR for this fn.
575577
// Note that this can be an intrinsic, if we are executing its fallback body.

compiler/rustc_const_eval/src/interpret/step.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
539539
}
540540
}
541541

542-
Drop { place, target, unwind, replace: _ } => {
542+
Drop { place, target, unwind, replace: _, drop, async_fut } => {
543+
assert!(
544+
async_fut.is_none() && drop.is_none(),
545+
"Async Drop must be expanded or reset to sync in runtime MIR"
546+
);
543547
let place = self.eval_place(place)?;
544548
let instance = Instance::resolve_drop_in_place(*self.tcx, place.layout.ty);
545549
if let ty::InstanceKind::DropGlue(_, None) = instance.def {

compiler/rustc_feature/src/unstable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,8 @@ declare_features! (
381381
(unstable, associated_const_equality, "1.58.0", Some(92827)),
382382
/// Allows associated type defaults.
383383
(unstable, associated_type_defaults, "1.2.0", Some(29661)),
384+
/// Allows implementing `AsyncDrop`.
385+
(incomplete, async_drop, "CURRENT_RUSTC_VERSION", Some(126482)),
384386
/// Allows async functions to be called from `dyn Trait`.
385387
(incomplete, async_fn_in_dyn_trait, "1.85.0", Some(133119)),
386388
/// Allows `#[track_caller]` on async functions.

compiler/rustc_hir/src/lang_items.rs

+7-13
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,10 @@ language_item_table! {
188188

189189
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
190190
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
191-
192-
AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::Exact(0);
193-
AsyncDestruct, sym::async_destruct, async_destruct_trait, Target::Trait, GenericRequirement::Exact(0);
191+
AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::None;
194192
AsyncDropInPlace, sym::async_drop_in_place, async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
195-
SurfaceAsyncDropInPlace, sym::surface_async_drop_in_place, surface_async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
196-
AsyncDropSurfaceDropInPlace, sym::async_drop_surface_drop_in_place, async_drop_surface_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
197-
AsyncDropSlice, sym::async_drop_slice, async_drop_slice_fn, Target::Fn, GenericRequirement::Exact(1);
198-
AsyncDropChain, sym::async_drop_chain, async_drop_chain_fn, Target::Fn, GenericRequirement::Exact(2);
199-
AsyncDropNoop, sym::async_drop_noop, async_drop_noop_fn, Target::Fn, GenericRequirement::Exact(0);
200-
AsyncDropDeferredDropInPlace, sym::async_drop_deferred_drop_in_place, async_drop_deferred_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
201-
AsyncDropFuse, sym::async_drop_fuse, async_drop_fuse_fn, Target::Fn, GenericRequirement::Exact(1);
202-
AsyncDropDefer, sym::async_drop_defer, async_drop_defer_fn, Target::Fn, GenericRequirement::Exact(1);
203-
AsyncDropEither, sym::async_drop_either, async_drop_either_fn, Target::Fn, GenericRequirement::Exact(3);
193+
AsyncDropInPlacePoll, sym::async_drop_in_place_poll, async_drop_in_place_poll_fn, Target::Closure, GenericRequirement::Exact(1);
194+
FutureDropPoll, sym::future_drop_poll, future_drop_poll_fn, Target::Fn, GenericRequirement::Exact(1);
204195

205196
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
206197
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
@@ -318,6 +309,10 @@ language_item_table! {
318309
PanicAsyncGenFnResumedPanic, sym::panic_const_async_gen_fn_resumed_panic, panic_const_async_gen_fn_resumed_panic, Target::Fn, GenericRequirement::None;
319310
PanicGenFnNonePanic, sym::panic_const_gen_fn_none_panic, panic_const_gen_fn_none_panic, Target::Fn, GenericRequirement::None;
320311
PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
312+
PanicCoroutineResumedDrop, sym::panic_const_coroutine_resumed_drop, panic_const_coroutine_resumed_drop, Target::Fn, GenericRequirement::None;
313+
PanicAsyncFnResumedDrop, sym::panic_const_async_fn_resumed_drop, panic_const_async_fn_resumed_drop, Target::Fn, GenericRequirement::None;
314+
PanicAsyncGenFnResumedDrop, sym::panic_const_async_gen_fn_resumed_drop, panic_const_async_gen_fn_resumed_drop, Target::Fn, GenericRequirement::None;
315+
PanicGenFnNoneDrop, sym::panic_const_gen_fn_none_drop, panic_const_gen_fn_none_drop, Target::Fn, GenericRequirement::None;
321316
/// libstd panic entry point. Necessary for const eval to be able to catch it
322317
BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
323318

@@ -330,7 +325,6 @@ language_item_table! {
330325

331326
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
332327
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
333-
FallbackSurfaceDrop, sym::fallback_surface_drop, fallback_surface_drop_fn, Target::Fn, GenericRequirement::None;
334328
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
335329

336330
/// For all binary crates without `#![no_main]`, Rust will generate a "main" function.

compiler/rustc_hir_typeck/src/callee.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ pub(crate) fn check_legal_trait_for_method_call(
3434
receiver: Option<Span>,
3535
expr_span: Span,
3636
trait_id: DefId,
37-
body_id: DefId,
37+
_body_id: DefId,
3838
) -> Result<(), ErrorGuaranteed> {
39-
if tcx.is_lang_item(trait_id, LangItem::Drop)
40-
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
41-
{
39+
if tcx.is_lang_item(trait_id, LangItem::Drop) {
4240
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
4341
errors::ExplicitDestructorCallSugg::Snippet {
4442
lo: expr_span.shrink_to_lo(),

compiler/rustc_interface/src/passes.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -979,11 +979,13 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
979979
let _ = tcx.ensure_ok().check_coroutine_obligations(
980980
tcx.typeck_root_def_id(def_id.to_def_id()).expect_local(),
981981
);
982-
// Eagerly check the unsubstituted layout for cycles.
983-
tcx.ensure_ok().layout_of(
984-
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
985-
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
986-
);
982+
if !tcx.is_async_drop_in_place_poll_fn(def_id.to_def_id()) {
983+
// Eagerly check the unsubstituted layout for cycles.
984+
tcx.ensure_ok().layout_of(
985+
ty::TypingEnv::post_analysis(tcx, def_id.to_def_id())
986+
.as_query_input(tcx.type_of(def_id).instantiate_identity()),
987+
);
988+
}
987989
}
988990
});
989991
});

compiler/rustc_middle/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
1+
middle_assert_async_resume_after_drop = `async fn` resumed after async drop
2+
13
middle_assert_async_resume_after_panic = `async fn` resumed after panicking
24
35
middle_assert_async_resume_after_return = `async fn` resumed after completion
46
7+
middle_assert_coroutine_resume_after_drop = coroutine resumed after async drop
8+
59
middle_assert_coroutine_resume_after_panic = coroutine resumed after panicking
610
711
middle_assert_coroutine_resume_after_return = coroutine resumed after completion
812
913
middle_assert_divide_by_zero =
1014
attempt to divide `{$val}` by zero
1115
16+
middle_assert_gen_resume_after_drop = `gen` fn or block cannot be further iterated on after it async dropped
17+
1218
middle_assert_gen_resume_after_panic = `gen` fn or block cannot be further iterated on after it panicked
1319
1420
middle_assert_misaligned_ptr_deref =

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ macro_rules! arena_types {
99
($macro:path) => (
1010
$macro!([
1111
[] layout: rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx>,
12+
[] proxy_coroutine_layout: rustc_middle::mir::CoroutineLayout<'tcx>,
1213
[] fn_abi: rustc_target::callconv::FnAbi<'tcx, rustc_middle::ty::Ty<'tcx>>,
1314
// AdtDef are interned and compared by address
1415
[decode] adt_def: rustc_middle::ty::AdtDefData,

0 commit comments

Comments
 (0)