Auto merge of #124662 - zetanumbers:needs_async_drop, r=oli-obk

Implement `needs_async_drop` in rustc and optimize async drop glue

This PR expands on #121801 and implements `Ty::needs_async_drop` which works almost exactly the same as `Ty::needs_drop`, which is needed for #123948.

Also made compiler's async drop code to look more like compiler's regular drop code, which enabled me to write an optimization where types which do not use `AsyncDrop` can simply forward async drop glue to `drop_in_place`. This made size of the async block from the [async_drop test](67980dd6fb/tests/ui/async-await/async-drop.rs) to decrease by 12%.
This commit is contained in:
bors 2024-05-31 10:12:24 +00:00
commit 99cb42c296
19 changed files with 382 additions and 194 deletions

View file

@ -12,7 +12,7 @@ use rustc_middle::mir::{
Terminator, TerminatorKind, UnwindAction, UnwindTerminateReason, RETURN_PLACE,
};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::util::{AsyncDropGlueMorphology, Discr};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::source_map::respan;
@ -116,15 +116,25 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
}
fn build(self) -> Body<'tcx> {
let (tcx, def_id, Some(self_ty)) = (self.tcx, self.def_id, self.self_ty) else {
let (tcx, Some(self_ty)) = (self.tcx, self.self_ty) else {
return self.build_zst_output();
};
match self_ty.async_drop_glue_morphology(tcx) {
AsyncDropGlueMorphology::Noop => span_bug!(
self.span,
"async drop glue shim generator encountered type with noop async drop glue morphology"
),
AsyncDropGlueMorphology::DeferredDropInPlace => {
return self.build_deferred_drop_in_place();
}
AsyncDropGlueMorphology::Custom => (),
}
let surface_drop_kind = || {
let param_env = tcx.param_env_reveal_all_normalized(def_id);
if self_ty.has_surface_async_drop(tcx, param_env) {
let adt_def = self_ty.ty_adt_def()?;
if adt_def.async_destructor(tcx).is_some() {
Some(SurfaceDropKind::Async)
} else if self_ty.has_surface_drop(tcx, param_env) {
} else if adt_def.destructor(tcx).is_some() {
Some(SurfaceDropKind::Sync)
} else {
None
@ -267,6 +277,13 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
self.return_()
}
fn build_deferred_drop_in_place(mut self) -> Body<'tcx> {
self.put_self();
let deferred = self.combine_deferred_drop_in_place();
self.combine_fuse(deferred);
self.return_()
}
fn build_fused_async_surface(mut self) -> Body<'tcx> {
self.put_self();
let surface = self.combine_async_surface();
@ -441,6 +458,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
)
}
fn combine_deferred_drop_in_place(&mut self) -> Ty<'tcx> {
self.apply_combinator(
1,
LangItem::AsyncDropDeferredDropInPlace,
&[self.self_ty.unwrap().into()],
)
}
fn combine_fuse(&mut self, inner_future_ty: Ty<'tcx>) -> Ty<'tcx> {
self.apply_combinator(1, LangItem::AsyncDropFuse, &[inner_future_ty.into()])
}
@ -481,7 +506,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
if let Some(ty) = self.self_ty {
debug_assert_eq!(
output.ty(&self.locals, self.tcx),
ty.async_destructor_ty(self.tcx, self.param_env),
ty.async_destructor_ty(self.tcx),
"output async destructor types did not match for type: {ty:?}",
);
}