Skip to content

Commit 24a24ec

Browse files
committed
Add simple async drop glue generation
Explainer: https://zetanumbers.github.io/book/async-drop-design.html #121801
1 parent 1dea922 commit 24a24ec

File tree

40 files changed

+1921
-20
lines changed

40 files changed

+1921
-20
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,24 @@ fn exported_symbols_provider_local(
363363
},
364364
));
365365
}
366+
MonoItem::Fn(Instance {
367+
def: InstanceDef::AsyncDropGlueCtorShim(def_id, ty),
368+
args,
369+
}) => {
370+
// A little sanity-check
371+
debug_assert_eq!(
372+
args.non_erasable_generics(tcx, def_id).skip(1).next(),
373+
Some(GenericArgKind::Type(ty))
374+
);
375+
symbols.push((
376+
ExportedSymbol::AsyncDropGlueCtorShim(ty),
377+
SymbolExportInfo {
378+
level: SymbolExportLevel::Rust,
379+
kind: SymbolExportKind::Text,
380+
used: false,
381+
},
382+
));
383+
}
366384
_ => {
367385
// Any other symbols don't qualify for sharing
368386
}
@@ -385,6 +403,7 @@ fn upstream_monomorphizations_provider(
385403
let mut instances: DefIdMap<UnordMap<_, _>> = Default::default();
386404

387405
let drop_in_place_fn_def_id = tcx.lang_items().drop_in_place_fn();
406+
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
388407

389408
for &cnum in cnums.iter() {
390409
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
@@ -399,6 +418,18 @@ fn upstream_monomorphizations_provider(
399418
continue;
400419
}
401420
}
421+
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
422+
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
423+
(
424+
async_drop_in_place_fn_def_id,
425+
tcx.mk_args(&[tcx.lifetimes.re_erased.into(), ty.into()]),
426+
)
427+
} else {
428+
// `drop_in_place` in place does not exist, don't try
429+
// to use it.
430+
continue;
431+
}
432+
}
402433
ExportedSymbol::NonGeneric(..)
403434
| ExportedSymbol::ThreadLocalShim(..)
404435
| ExportedSymbol::NoDefId(..) => {
@@ -534,6 +565,13 @@ pub fn symbol_name_for_instance_in_crate<'tcx>(
534565
Instance::resolve_drop_in_place(tcx, ty),
535566
instantiating_crate,
536567
),
568+
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
569+
rustc_symbol_mangling::symbol_name_for_instance_in_crate(
570+
tcx,
571+
Instance::resolve_async_drop_in_place(tcx, ty),
572+
instantiating_crate,
573+
)
574+
}
537575
ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(),
538576
}
539577
}
@@ -582,6 +620,9 @@ pub fn linking_symbol_name_for_instance_in_crate<'tcx>(
582620
// DropGlue always use the Rust calling convention and thus follow the target's default
583621
// symbol decoration scheme.
584622
ExportedSymbol::DropGlue(..) => None,
623+
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
624+
// target's default symbol decoration scheme.
625+
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
585626
// NoDefId always follow the target's default symbol decoration scheme.
586627
ExportedSymbol::NoDefId(..) => None,
587628
// ThreadLocalShim always follow the target's default symbol decoration scheme.

compiler/rustc_const_eval/src/interpret/terminator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
558558
| ty::InstanceDef::CloneShim(..)
559559
| ty::InstanceDef::FnPtrAddrShim(..)
560560
| ty::InstanceDef::ThreadLocalShim(..)
561+
| ty::InstanceDef::AsyncDropGlueCtorShim(..)
561562
| ty::InstanceDef::Item(_) => {
562563
// We need MIR for this fn
563564
let Some((body, instance)) = M::find_mir_or_eval_fn(

compiler/rustc_hir/src/lang_items.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,18 @@ language_item_table! {
162162
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
163163
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
164164

165+
AsyncDrop, sym::async_drop, async_drop_trait, Target::Trait, GenericRequirement::Exact(0);
166+
AsyncDestruct, sym::async_destruct, async_destruct_trait, Target::Trait, GenericRequirement::Exact(0);
167+
AsyncDropInPlace, sym::async_drop_in_place, async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
168+
SurfaceAsyncDropInPlace, sym::surface_async_drop_in_place, surface_async_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
169+
AsyncDropSurfaceDropInPlace, sym::async_drop_surface_drop_in_place, async_drop_surface_drop_in_place_fn, Target::Fn, GenericRequirement::Exact(1);
170+
AsyncDropSlice, sym::async_drop_slice, async_drop_slice_fn, Target::Fn, GenericRequirement::Exact(1);
171+
AsyncDropChain, sym::async_drop_chain, async_drop_chain_fn, Target::Fn, GenericRequirement::Exact(2);
172+
AsyncDropNoop, sym::async_drop_noop, async_drop_noop_fn, Target::Fn, GenericRequirement::Exact(0);
173+
AsyncDropFuse, sym::async_drop_fuse, async_drop_fuse_fn, Target::Fn, GenericRequirement::Exact(1);
174+
AsyncDropDefer, sym::async_drop_defer, async_drop_defer_fn, Target::Fn, GenericRequirement::Exact(1);
175+
AsyncDropEither, sym::async_drop_either, async_drop_either_fn, Target::Fn, GenericRequirement::Exact(3);
176+
165177
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
166178
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
167179

@@ -281,6 +293,7 @@ language_item_table! {
281293

282294
ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
283295
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
296+
FallbackSurfaceDrop, sym::fallback_surface_drop, fallback_surface_drop_fn, Target::Fn, GenericRequirement::None;
284297
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
285298

286299
Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,11 @@ pub fn check_legal_trait_for_method_call(
3838
receiver: Option<Span>,
3939
expr_span: Span,
4040
trait_id: DefId,
41+
body_id: DefId,
4142
) -> Result<(), ErrorGuaranteed> {
42-
if tcx.lang_items().drop_trait() == Some(trait_id) {
43+
if tcx.lang_items().drop_trait() == Some(trait_id)
44+
&& tcx.lang_items().fallback_surface_drop_fn() != Some(body_id)
45+
{
4346
let sugg = if let Some(receiver) = receiver.filter(|s| !s.is_empty()) {
4447
errors::ExplicitDestructorCallSugg::Snippet {
4548
lo: expr_span.shrink_to_lo(),

compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11181118
None,
11191119
span,
11201120
container_id,
1121+
self.body_id.to_def_id(),
11211122
) {
11221123
self.set_tainted_by_errors(e);
11231124
}

compiler/rustc_hir_typeck/src/method/confirm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -628,6 +628,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
628628
Some(self.self_expr.span),
629629
self.call_expr.span,
630630
trait_def_id,
631+
self.body_id.to_def_id(),
631632
) {
632633
self.set_tainted_by_errors(e);
633634
}

compiler/rustc_middle/src/middle/exported_symbols.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub enum ExportedSymbol<'tcx> {
4343
NonGeneric(DefId),
4444
Generic(DefId, GenericArgsRef<'tcx>),
4545
DropGlue(Ty<'tcx>),
46+
AsyncDropGlueCtorShim(Ty<'tcx>),
4647
ThreadLocalShim(DefId),
4748
NoDefId(ty::SymbolName<'tcx>),
4849
}
@@ -59,6 +60,9 @@ impl<'tcx> ExportedSymbol<'tcx> {
5960
ExportedSymbol::DropGlue(ty) => {
6061
tcx.symbol_name(ty::Instance::resolve_drop_in_place(tcx, ty))
6162
}
63+
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
64+
tcx.symbol_name(ty::Instance::resolve_async_drop_in_place(tcx, ty))
65+
}
6266
ExportedSymbol::ThreadLocalShim(def_id) => tcx.symbol_name(ty::Instance {
6367
def: ty::InstanceDef::ThreadLocalShim(def_id),
6468
args: ty::GenericArgs::empty(),

compiler/rustc_middle/src/mir/mono.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,8 @@ impl<'tcx> CodegenUnit<'tcx> {
406406
| InstanceDef::DropGlue(..)
407407
| InstanceDef::CloneShim(..)
408408
| InstanceDef::ThreadLocalShim(..)
409-
| InstanceDef::FnPtrAddrShim(..) => None,
409+
| InstanceDef::FnPtrAddrShim(..)
410+
| InstanceDef::AsyncDropGlueCtorShim(..) => None,
410411
}
411412
}
412413
MonoItem::Static(def_id) => def_id.as_local().map(Idx::index),

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,17 @@ fn dump_path<'tcx>(
187187
}));
188188
s
189189
}
190+
ty::InstanceDef::AsyncDropGlueCtorShim(_, ty) => {
191+
// Unfortunately, pretty-printed typed are not very filename-friendly.
192+
// We dome some filtering.
193+
let mut s = ".".to_owned();
194+
s.extend(ty.to_string().chars().filter_map(|c| match c {
195+
' ' => None,
196+
':' | '<' | '>' => Some('_'),
197+
c => Some(c),
198+
}));
199+
s
200+
}
190201
_ => String::new(),
191202
};
192203

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,8 @@ macro_rules! make_mir_visitor {
355355
ty::InstanceDef::FnPtrShim(_def_id, ty) |
356356
ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
357357
ty::InstanceDef::CloneShim(_def_id, ty) |
358-
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) => {
358+
ty::InstanceDef::FnPtrAddrShim(_def_id, ty) |
359+
ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, ty) => {
359360
// FIXME(eddyb) use a better `TyContext` here.
360361
self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
361362
}

compiler/rustc_middle/src/query/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,14 @@ rustc_queries! {
13441344
query is_unpin_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
13451345
desc { "computing whether `{}` is `Unpin`", env.value }
13461346
}
1347+
/// Query backing `Ty::has_surface_async_drop`.
1348+
query has_surface_async_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
1349+
desc { "computing whether `{}` has `AsyncDrop` implementation", env.value }
1350+
}
1351+
/// Query backing `Ty::has_surface_drop`.
1352+
query has_surface_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
1353+
desc { "computing whether `{}` has `Drop` implementation", env.value }
1354+
}
13471355
/// Query backing `Ty::needs_drop`.
13481356
query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool {
13491357
desc { "computing whether `{}` needs drop", env.value }

compiler/rustc_middle/src/ty/instance.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ pub enum InstanceDef<'tcx> {
168168
///
169169
/// The `DefId` is for `FnPtr::addr`, the `Ty` is the type `T`.
170170
FnPtrAddrShim(DefId, Ty<'tcx>),
171+
172+
/// `core::future::async_drop::async_drop_in_place::<'_, T>`.
173+
///
174+
/// The `DefId` is for `core::future::async_drop::async_drop_in_place`, the `Ty`
175+
/// is the type `T`.
176+
AsyncDropGlueCtorShim(DefId, Ty<'tcx>),
171177
}
172178

173179
impl<'tcx> Instance<'tcx> {
@@ -210,7 +216,9 @@ impl<'tcx> Instance<'tcx> {
210216
InstanceDef::Item(def) => tcx
211217
.upstream_monomorphizations_for(def)
212218
.and_then(|monos| monos.get(&self.args).cloned()),
213-
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
219+
InstanceDef::DropGlue(_, Some(_)) | InstanceDef::AsyncDropGlueCtorShim(_, _) => {
220+
tcx.upstream_drop_glue_for(self.args)
221+
}
214222
_ => None,
215223
}
216224
}
@@ -235,17 +243,18 @@ impl<'tcx> InstanceDef<'tcx> {
235243
| ty::InstanceDef::CoroutineKindShim { coroutine_def_id: def_id }
236244
| InstanceDef::DropGlue(def_id, _)
237245
| InstanceDef::CloneShim(def_id, _)
238-
| InstanceDef::FnPtrAddrShim(def_id, _) => def_id,
246+
| InstanceDef::FnPtrAddrShim(def_id, _)
247+
| InstanceDef::AsyncDropGlueCtorShim(def_id, _) => def_id,
239248
}
240249
}
241250

242251
/// Returns the `DefId` of instances which might not require codegen locally.
243252
pub fn def_id_if_not_guaranteed_local_codegen(self) -> Option<DefId> {
244253
match self {
245254
ty::InstanceDef::Item(def) => Some(def),
246-
ty::InstanceDef::DropGlue(def_id, Some(_)) | InstanceDef::ThreadLocalShim(def_id) => {
247-
Some(def_id)
248-
}
255+
ty::InstanceDef::DropGlue(def_id, Some(_))
256+
| InstanceDef::AsyncDropGlueCtorShim(def_id, _)
257+
| InstanceDef::ThreadLocalShim(def_id) => Some(def_id),
249258
InstanceDef::VTableShim(..)
250259
| InstanceDef::ReifyShim(..)
251260
| InstanceDef::FnPtrShim(..)
@@ -347,7 +356,8 @@ impl<'tcx> InstanceDef<'tcx> {
347356
| InstanceDef::ThreadLocalShim(..)
348357
| InstanceDef::FnPtrAddrShim(..)
349358
| InstanceDef::FnPtrShim(..)
350-
| InstanceDef::DropGlue(_, Some(_)) => false,
359+
| InstanceDef::DropGlue(_, Some(_))
360+
| InstanceDef::AsyncDropGlueCtorShim(..) => false,
351361
InstanceDef::ClosureOnceShim { .. }
352362
| InstanceDef::ConstructCoroutineInClosureShim { .. }
353363
| InstanceDef::CoroutineKindShim { .. }
@@ -396,6 +406,7 @@ fn fmt_instance(
396406
InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
397407
InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"),
398408
InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
409+
InstanceDef::AsyncDropGlueCtorShim(_, ty) => write!(f, " - shim({ty})"),
399410
}
400411
}
401412

@@ -638,6 +649,12 @@ impl<'tcx> Instance<'tcx> {
638649
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
639650
}
640651

652+
pub fn resolve_async_drop_in_place(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ty::Instance<'tcx> {
653+
let def_id = tcx.require_lang_item(LangItem::AsyncDropInPlace, None);
654+
let args = tcx.mk_args(&[ty.into()]);
655+
Instance::expect_resolve(tcx, ty::ParamEnv::reveal_all(), def_id, args)
656+
}
657+
641658
#[instrument(level = "debug", skip(tcx), ret)]
642659
pub fn fn_once_adapter_instance(
643660
tcx: TyCtxt<'tcx>,

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1797,7 +1797,8 @@ impl<'tcx> TyCtxt<'tcx> {
17971797
| ty::InstanceDef::DropGlue(..)
17981798
| ty::InstanceDef::CloneShim(..)
17991799
| ty::InstanceDef::ThreadLocalShim(..)
1800-
| ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance),
1800+
| ty::InstanceDef::FnPtrAddrShim(..)
1801+
| ty::InstanceDef::AsyncDropGlueCtorShim(..) => self.mir_shims(instance),
18011802
}
18021803
}
18031804

0 commit comments

Comments
 (0)