Skip to content

Commit 023acf6

Browse files
committed
Make async drop code more consistent with regular drop code
Fixes #126573
1 parent f9515fd commit 023acf6

File tree

4 files changed

+67
-14
lines changed

4 files changed

+67
-14
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ fn exported_symbols_provider_local(
371371
}) => {
372372
// A little sanity-check
373373
debug_assert_eq!(
374-
args.non_erasable_generics(tcx, def_id).skip(1).next(),
374+
args.non_erasable_generics(tcx, def_id).next(),
375375
Some(GenericArgKind::Type(ty))
376376
);
377377
symbols.push((
@@ -422,10 +422,7 @@ fn upstream_monomorphizations_provider(
422422
}
423423
ExportedSymbol::AsyncDropGlueCtorShim(ty) => {
424424
if let Some(async_drop_in_place_fn_def_id) = async_drop_in_place_fn_def_id {
425-
(
426-
async_drop_in_place_fn_def_id,
427-
tcx.mk_args(&[tcx.lifetimes.re_erased.into(), ty.into()]),
428-
)
425+
(async_drop_in_place_fn_def_id, tcx.mk_args(&[ty.into()]))
429426
} else {
430427
// `drop_in_place` in place does not exist, don't try
431428
// to use it.
@@ -480,6 +477,17 @@ fn upstream_drop_glue_for_provider<'tcx>(
480477
}
481478
}
482479

480+
fn upstream_async_drop_glue_for_provider<'tcx>(
481+
tcx: TyCtxt<'tcx>,
482+
args: GenericArgsRef<'tcx>,
483+
) -> Option<CrateNum> {
484+
if let Some(def_id) = tcx.lang_items().async_drop_in_place_fn() {
485+
tcx.upstream_monomorphizations_for(def_id).and_then(|monos| monos.get(&args).cloned())
486+
} else {
487+
None
488+
}
489+
}
490+
483491
fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
484492
!tcx.reachable_set(()).contains(&def_id)
485493
}
@@ -491,6 +499,7 @@ pub fn provide(providers: &mut Providers) {
491499
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
492500
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
493501
providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;
502+
providers.upstream_async_drop_glue_for = upstream_async_drop_glue_for_provider;
494503
providers.wasm_import_module_map = wasm_import_module_map;
495504
providers.extern_queries.is_reachable_non_generic = is_reachable_non_generic_provider_extern;
496505
providers.extern_queries.upstream_monomorphizations_for =

compiler/rustc_middle/src/query/mod.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -1549,12 +1549,13 @@ rustc_queries! {
15491549
}
15501550
}
15511551

1552-
/// The entire set of monomorphizations the local crate can safely link
1553-
/// to because they are exported from upstream crates. Do not depend on
1554-
/// this directly, as its value changes anytime a monomorphization gets
1555-
/// added or removed in any upstream crate. Instead use the narrower
1556-
/// `upstream_monomorphizations_for`, `upstream_drop_glue_for`, or, even
1557-
/// better, `Instance::upstream_monomorphization()`.
1552+
/// The entire set of monomorphizations the local crate can safely
1553+
/// link to because they are exported from upstream crates. Do
1554+
/// not depend on this directly, as its value changes anytime
1555+
/// a monomorphization gets added or removed in any upstream
1556+
/// crate. Instead use the narrower `upstream_monomorphizations_for`,
1557+
/// `upstream_drop_glue_for`, `upstream_async_drop_glue_for`, or,
1558+
/// even better, `Instance::upstream_monomorphization()`.
15581559
query upstream_monomorphizations(_: ()) -> &'tcx DefIdMap<UnordMap<GenericArgsRef<'tcx>, CrateNum>> {
15591560
arena_cache
15601561
desc { "collecting available upstream monomorphizations" }
@@ -1596,6 +1597,26 @@ rustc_queries! {
15961597
desc { "available upstream drop-glue for `{:?}`", args }
15971598
}
15981599

1600+
/// Returns the upstream crate that exports async-drop-glue for
1601+
/// the given type (`args` is expected to be a single-item list
1602+
/// containing the type one wants async-drop-glue for).
1603+
///
1604+
/// This is a subset of `upstream_monomorphizations_for` in order
1605+
/// to increase dep-tracking granularity. Otherwise adding or
1606+
/// removing any type with async-drop-glue in any upstream crate
1607+
/// would invalidate all functions calling async-drop-glue of an
1608+
/// upstream type.
1609+
///
1610+
/// You likely want to call `Instance::upstream_monomorphization()`
1611+
/// instead of invoking this query directly.
1612+
///
1613+
/// NOTE: This query could easily be extended to also support other
1614+
/// common functions that have are large set of monomorphizations
1615+
/// (like `Clone::clone` for example).
1616+
query upstream_async_drop_glue_for(args: GenericArgsRef<'tcx>) -> Option<CrateNum> {
1617+
desc { "available upstream async-drop-glue for `{:?}`", args }
1618+
}
1619+
15991620
/// Returns a list of all `extern` blocks of a crate.
16001621
query foreign_modules(_: CrateNum) -> &'tcx FxIndexMap<DefId, ForeignModule> {
16011622
arena_cache

compiler/rustc_middle/src/ty/instance.rs

+25-3
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,9 @@ impl<'tcx> Instance<'tcx> {
219219
InstanceDef::Item(def) => tcx
220220
.upstream_monomorphizations_for(def)
221221
.and_then(|monos| monos.get(&self.args).cloned()),
222-
InstanceDef::DropGlue(_, Some(_)) | InstanceDef::AsyncDropGlueCtorShim(_, _) => {
223-
tcx.upstream_drop_glue_for(self.args)
222+
InstanceDef::DropGlue(_, Some(_)) => tcx.upstream_drop_glue_for(self.args),
223+
InstanceDef::AsyncDropGlueCtorShim(_, Some(_)) => {
224+
tcx.upstream_async_drop_glue_for(self.args)
224225
}
225226
_ => None,
226227
}
@@ -256,7 +257,7 @@ impl<'tcx> InstanceDef<'tcx> {
256257
match self {
257258
ty::InstanceDef::Item(def) => Some(def),
258259
ty::InstanceDef::DropGlue(def_id, Some(_))
259-
| InstanceDef::AsyncDropGlueCtorShim(def_id, _)
260+
| InstanceDef::AsyncDropGlueCtorShim(def_id, Some(_))
260261
| InstanceDef::ThreadLocalShim(def_id) => Some(def_id),
261262
InstanceDef::VTableShim(..)
262263
| InstanceDef::ReifyShim(..)
@@ -267,6 +268,7 @@ impl<'tcx> InstanceDef<'tcx> {
267268
| ty::InstanceDef::ConstructCoroutineInClosureShim { .. }
268269
| ty::InstanceDef::CoroutineKindShim { .. }
269270
| InstanceDef::DropGlue(..)
271+
| InstanceDef::AsyncDropGlueCtorShim(..)
270272
| InstanceDef::CloneShim(..)
271273
| InstanceDef::FnPtrAddrShim(..) => None,
272274
}
@@ -332,6 +334,26 @@ impl<'tcx> InstanceDef<'tcx> {
332334
.map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.did))
333335
});
334336
}
337+
if let ty::InstanceDef::AsyncDropGlueCtorShim(.., Some(ty)) = *self {
338+
// Async drop glue generally wants to be instantiated at
339+
// every codegen unit, but without an #[inline] hint. We
340+
// should make this available to normal end-users.
341+
if tcx.sess.opts.incremental.is_none() {
342+
return true;
343+
}
344+
// When compiling with incremental, we can generate a *lot* of
345+
// codegen units. Including drop glue into all of them has a
346+
// considerable compile time cost.
347+
//
348+
// We include enums without destructors to allow, say, optimizing
349+
// drops of `Option::None` before LTO. We also respect the intent of
350+
// `#[inline]` on `Drop::drop` implementations.
351+
return ty.ty_adt_def().map_or(true, |adt_def| {
352+
adt_def
353+
.async_destructor(tcx)
354+
.map_or_else(|| adt_def.is_enum(), |dtor| tcx.cross_crate_inlinable(dtor.ctor))
355+
});
356+
}
335357
if let ty::InstanceDef::ThreadLocalShim(..) = *self {
336358
return false;
337359
}

compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs

+1
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ pub fn transform_instance<'tcx>(
288288
mut instance: Instance<'tcx>,
289289
options: TransformTyOptions,
290290
) -> Instance<'tcx> {
291+
// FIXME: account for async-drop-glue
291292
if (matches!(instance.def, ty::InstanceDef::Virtual(..))
292293
&& Some(instance.def_id()) == tcx.lang_items().drop_in_place_fn())
293294
|| matches!(instance.def, ty::InstanceDef::DropGlue(..))

0 commit comments

Comments
 (0)