about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs3
-rw-r--r--compiler/rustc_middle/src/ty/instance.rs5
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs43
-rw-r--r--compiler/rustc_middle/src/ty/util.rs117
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs80
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs3
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs53
13 files changed, 150 insertions, 182 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 008543e4470..cce3f0e6f2d 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -364,7 +364,7 @@ fn exported_symbols_provider_local(
                     ));
                 }
                 MonoItem::Fn(Instance {
-                    def: InstanceDef::AsyncDropGlueCtorShim(def_id, ty),
+                    def: InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty)),
                     args,
                 }) => {
                     // A little sanity-check
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index d81a9772a09..151170d78f4 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -187,7 +187,7 @@ fn dump_path<'tcx>(
             }));
             s
         }
-        ty::InstanceDef::AsyncDropGlueCtorShim(_, ty) => {
+        ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => {
             // Unfortunately, pretty-printed typed are not very filename-friendly.
             // We dome some filtering.
             let mut s = ".".to_owned();
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 01bd10c2007..1c38a69c7ec 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -350,13 +350,14 @@ macro_rules! make_mir_visitor {
                             receiver_by_ref: _,
                         } |
                         ty::InstanceDef::CoroutineKindShim { coroutine_def_id: _def_id } |
+                        ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, None) |
                         ty::InstanceDef::DropGlue(_def_id, None) => {}
 
                         ty::InstanceDef::FnPtrShim(_def_id, ty) |
                         ty::InstanceDef::DropGlue(_def_id, Some(ty)) |
                         ty::InstanceDef::CloneShim(_def_id, ty) |
                         ty::InstanceDef::FnPtrAddrShim(_def_id, ty) |
-                        ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, ty) => {
+                        ty::InstanceDef::AsyncDropGlueCtorShim(_def_id, Some(ty)) => {
                             // FIXME(eddyb) use a better `TyContext` here.
                             self.visit_ty($(& $mutability)? *ty, TyContext::Location(location));
                         }
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index 904f1aff94b..c7c4225c80e 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -173,7 +173,7 @@ pub enum InstanceDef<'tcx> {
     ///
     /// The `DefId` is for `core::future::async_drop::async_drop_in_place`, the `Ty`
     /// is the type `T`.
-    AsyncDropGlueCtorShim(DefId, Ty<'tcx>),
+    AsyncDropGlueCtorShim(DefId, Option<Ty<'tcx>>),
 }
 
 impl<'tcx> Instance<'tcx> {
@@ -406,7 +406,8 @@ fn fmt_instance(
         InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
         InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"),
         InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"),
-        InstanceDef::AsyncDropGlueCtorShim(_, ty) => write!(f, " - shim({ty})"),
+        InstanceDef::AsyncDropGlueCtorShim(_, None) => write!(f, " - shim(None)"),
+        InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) => write!(f, " - shim(Some({ty}))"),
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 135ade6d684..2a2781655c4 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2319,6 +2319,10 @@ impl<'tcx> Ty<'tcx> {
 
     /// Returns the type of the async destructor of this type.
     pub fn async_destructor_ty(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Ty<'tcx> {
+        if self.is_async_destructor_noop(tcx, param_env) || matches!(self.kind(), ty::Error(_)) {
+            return Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop)
+                .instantiate_identity();
+        }
         match *self.kind() {
             ty::Param(_) | ty::Alias(..) | ty::Infer(ty::TyVar(_)) => {
                 let assoc_items = tcx
@@ -2333,9 +2337,6 @@ impl<'tcx> Ty<'tcx> {
                     .instantiate(tcx, &[dtor.into()])
             }
 
-            ty::Adt(adt_def, _) if adt_def.is_manually_drop() => {
-                Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop).instantiate_identity()
-            }
             ty::Adt(adt_def, args) if adt_def.is_enum() || adt_def.is_struct() => self
                 .adt_async_destructor_ty(
                     tcx,
@@ -2357,34 +2358,10 @@ impl<'tcx> Ty<'tcx> {
             ty::Adt(adt_def, _) => {
                 assert!(adt_def.is_union());
 
-                match self.surface_async_dropper_ty(tcx, param_env) {
-                    None => Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop)
-                        .instantiate_identity(),
-                    Some(surface_drop) => {
-                        Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
-                            .instantiate(tcx, &[surface_drop.into()])
-                    }
-                }
-            }
-
-            ty::Never
-            | ty::Bool
-            | ty::Char
-            | ty::Int(_)
-            | ty::Uint(_)
-            | ty::Float(_)
-            | ty::Str
-            | ty::RawPtr(_, _)
-            | ty::Ref(..)
-            | ty::FnDef(..)
-            | ty::FnPtr(..)
-            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
-            | ty::Error(_) => {
-                Ty::async_destructor_combinator(tcx, LangItem::AsyncDropNoop).instantiate_identity()
-            }
+                let surface_drop = self.surface_async_dropper_ty(tcx, param_env).unwrap();
 
-            ty::Dynamic(..) | ty::CoroutineWitness(..) | ty::Coroutine(..) | ty::Pat(..) => {
-                bug!("`async_destructor_ty` is not yet implemented for type: {self:?}")
+                Ty::async_destructor_combinator(tcx, LangItem::AsyncDropFuse)
+                    .instantiate(tcx, &[surface_drop.into()])
             }
 
             ty::Bound(..)
@@ -2393,6 +2370,8 @@ impl<'tcx> Ty<'tcx> {
             | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("`async_destructor_ty` applied to unexpected type: {self:?}")
             }
+
+            _ => bug!("`async_destructor_ty` is not yet implemented for type: {self:?}"),
         }
     }
 
@@ -2406,6 +2385,8 @@ impl<'tcx> Ty<'tcx> {
         I: Iterator + ExactSizeIterator,
         I::Item: IntoIterator<Item = Ty<'tcx>>,
     {
+        debug_assert!(!self.is_async_destructor_noop(tcx, param_env));
+
         let defer = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropDefer);
         let chain = Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain);
 
@@ -2425,7 +2406,7 @@ impl<'tcx> Ty<'tcx> {
             .reduce(|other, matched| {
                 either.instantiate(tcx, &[other.into(), matched.into(), self.into()])
             })
-            .unwrap_or(noop);
+            .unwrap();
 
         let dtor = if let Some(dropper_ty) = self.surface_async_dropper_ty(tcx, param_env) {
             Ty::async_destructor_combinator(tcx, LangItem::AsyncDropChain)
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 1c3e8ffc13e..cd9d17cf930 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1306,8 +1306,7 @@ impl<'tcx> Ty<'tcx> {
     /// Checks whether values of this type `T` implements the `AsyncDrop`
     /// trait.
     pub fn has_surface_async_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
-        self.trivially_has_surface_async_drop()
-            && tcx.has_surface_async_drop_raw(param_env.and(self))
+        self.could_have_surface_async_drop() && tcx.has_surface_async_drop_raw(param_env.and(self))
     }
 
     /// Fast path helper for testing if a type has `AsyncDrop`
@@ -1316,52 +1315,68 @@ impl<'tcx> Ty<'tcx> {
     /// Returning `false` means the type is known to not have `AsyncDrop`
     /// implementation. Returning `true` means nothing -- could be
     /// `AsyncDrop`, might not be.
-    fn trivially_has_surface_async_drop(self) -> bool {
-        match self.kind() {
-            ty::Int(_)
-            | ty::Uint(_)
-            | ty::Float(_)
-            | ty::Bool
-            | ty::Char
-            | ty::Str
-            | ty::Never
-            | ty::Ref(..)
-            | ty::RawPtr(_, _)
-            | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Error(_)
-            | ty::Tuple(_)
-            | ty::Slice(_)
-            | ty::Array(_, _)
-            | ty::Closure(..)
-            | ty::CoroutineClosure(..)
-            | ty::Coroutine(..)
-            | ty::CoroutineWitness(..)
-            | ty::Pat(..) => false,
-            ty::Adt(..)
-            | ty::Bound(..)
-            | ty::Dynamic(..)
-            | ty::Foreign(_)
-            | ty::Infer(_)
-            | ty::Alias(..)
-            | ty::Param(_)
-            | ty::Placeholder(_) => true,
-        }
+    fn could_have_surface_async_drop(self) -> bool {
+        !self.is_async_destructor_trivially_noop()
+            && !matches!(
+                self.kind(),
+                ty::Tuple(_)
+                    | ty::Slice(_)
+                    | ty::Array(_, _)
+                    | ty::Closure(..)
+                    | ty::CoroutineClosure(..)
+                    | ty::Coroutine(..)
+            )
     }
 
     /// Checks whether values of this type `T` implements the `AsyncDrop`
     /// trait.
     pub fn has_surface_drop(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
-        self.trivially_has_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self))
+        self.could_have_surface_drop() && tcx.has_surface_drop_raw(param_env.and(self))
     }
 
-    /// Fast path helper for testing if a type has `AsyncDrop`
-    /// implementation.
+    /// Fast path helper for testing if a type has `Drop` implementation.
     ///
-    /// Returning `false` means the type is known to not have `AsyncDrop`
+    /// Returning `false` means the type is known to not have `Drop`
     /// implementation. Returning `true` means nothing -- could be
-    /// `AsyncDrop`, might not be.
-    fn trivially_has_surface_drop(self) -> bool {
+    /// `Drop`, might not be.
+    fn could_have_surface_drop(self) -> bool {
+        self.is_async_destructor_trivially_noop()
+            && !matches!(
+                self.kind(),
+                ty::Tuple(_)
+                    | ty::Slice(_)
+                    | ty::Array(_, _)
+                    | ty::Closure(..)
+                    | ty::CoroutineClosure(..)
+                    | ty::Coroutine(..)
+            )
+    }
+
+    /// Checks whether values of this type `T` implement has noop async destructor.
+    //
+    // FIXME: implement optimization to make ADTs, which do not need drop,
+    // to skip fields or to have noop async destructor.
+    pub fn is_async_destructor_noop(
+        self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+    ) -> bool {
+        self.is_async_destructor_trivially_noop()
+            || if let ty::Adt(adt_def, _) = self.kind() {
+                (adt_def.is_union() || adt_def.is_payloadfree())
+                    && !self.has_surface_async_drop(tcx, param_env)
+                    && !self.has_surface_drop(tcx, param_env)
+            } else {
+                false
+            }
+    }
+
+    /// Fast path helper for testing if a type has noop async destructor.
+    ///
+    /// Returning `true` means the type is known to have noop async destructor
+    /// implementation. Returning `true` means nothing -- could be
+    /// `Drop`, might not be.
+    fn is_async_destructor_trivially_noop(self) -> bool {
         match self.kind() {
             ty::Int(_)
             | ty::Uint(_)
@@ -1371,26 +1386,12 @@ impl<'tcx> Ty<'tcx> {
             | ty::Str
             | ty::Never
             | ty::Ref(..)
-            | ty::RawPtr(_, _)
+            | ty::RawPtr(..)
             | ty::FnDef(..)
-            | ty::FnPtr(_)
-            | ty::Error(_)
-            | ty::Tuple(_)
-            | ty::Slice(_)
-            | ty::Array(_, _)
-            | ty::Closure(..)
-            | ty::CoroutineClosure(..)
-            | ty::Coroutine(..)
-            | ty::CoroutineWitness(..)
-            | ty::Pat(..) => false,
-            ty::Adt(..)
-            | ty::Bound(..)
-            | ty::Dynamic(..)
-            | ty::Foreign(_)
-            | ty::Infer(_)
-            | ty::Alias(..)
-            | ty::Param(_)
-            | ty::Placeholder(_) => true,
+            | ty::FnPtr(_) => true,
+            ty::Tuple(tys) => tys.is_empty(),
+            ty::Adt(adt_def, _) => adt_def.is_manually_drop(),
+            _ => false,
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 365e3dc36d4..1af03a5afe5 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -1072,8 +1072,8 @@ fn try_instance_mir<'tcx>(
     tcx: TyCtxt<'tcx>,
     instance: InstanceDef<'tcx>,
 ) -> Result<&'tcx Body<'tcx>, &'static str> {
-    if let ty::InstanceDef::DropGlue(_, Some(ty)) | ty::InstanceDef::AsyncDropGlueCtorShim(_, ty) =
-        instance
+    if let ty::InstanceDef::DropGlue(_, Some(ty))
+    | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(ty)) = instance
         && let ty::Adt(def, args) = ty.kind()
     {
         let fields = def.all_fields();
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index 095f41fb3d8..a423e324781 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -24,9 +24,11 @@ use super::{local_decls_for_sig, new_body};
 pub fn build_async_destructor_ctor_shim<'tcx>(
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    self_ty: Ty<'tcx>,
+    ty: Option<Ty<'tcx>>,
 ) -> Body<'tcx> {
-    AsyncDestructorCtorShimBuilder::new(tcx, def_id, self_ty).build()
+    debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty);
+
+    AsyncDestructorCtorShimBuilder::new(tcx, def_id, ty).build()
 }
 
 /// Builder for async_drop_in_place shim. Functions as a stack machine
@@ -40,7 +42,7 @@ pub fn build_async_destructor_ctor_shim<'tcx>(
 struct AsyncDestructorCtorShimBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
     def_id: DefId,
-    self_ty: Ty<'tcx>,
+    self_ty: Option<Ty<'tcx>>,
     span: Span,
     source_info: SourceInfo,
     param_env: ty::ParamEnv<'tcx>,
@@ -64,12 +66,12 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
     const INPUT_COUNT: usize = 1;
     const MAX_STACK_LEN: usize = 2;
 
-    fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Self {
+    fn new(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Option<Ty<'tcx>>) -> Self {
+        // Assuming `async_drop_in_place::<()>` is the same as for any type with noop async destructor
+        let arg_ty = if let Some(ty) = self_ty { ty } else { tcx.types.unit };
+        let sig = tcx.fn_sig(def_id).instantiate(tcx, &[arg_ty.into()]);
+        let sig = tcx.instantiate_bound_regions_with_erased(sig);
         let span = tcx.def_span(def_id);
-        let Some(sig) = tcx.fn_sig(def_id).instantiate(tcx, &[self_ty.into()]).no_bound_vars()
-        else {
-            span_bug!(span, "async_drop_in_place_raw with bound vars for `{self_ty}`");
-        };
 
         let source_info = SourceInfo::outermost(span);
 
@@ -110,7 +112,9 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
     }
 
     fn build(self) -> Body<'tcx> {
-        let (tcx, def_id, self_ty) = (self.tcx, self.def_id, self.self_ty);
+        let (tcx, def_id, Some(self_ty)) = (self.tcx, self.def_id, self.self_ty) else {
+            return self.build_noop();
+        };
 
         let surface_drop_kind = || {
             let param_env = tcx.param_env_reveal_all_normalized(def_id);
@@ -127,8 +131,6 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
             ty::Array(elem_ty, _) => self.build_slice(true, *elem_ty),
             ty::Slice(elem_ty) => self.build_slice(false, *elem_ty),
 
-            ty::Adt(adt_def, _) if adt_def.is_manually_drop() => self.build_noop(),
-
             ty::Tuple(elem_tys) => self.build_chain(None, elem_tys.iter()),
             ty::Adt(adt_def, args) if adt_def.is_struct() => {
                 let field_tys = adt_def.non_enum_variant().fields.iter().map(|f| f.ty(tcx, args));
@@ -143,35 +145,14 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
                 self.build_enum(*adt_def, *args, surface_drop_kind())
             }
 
-            ty::Never
-            | ty::Bool
-            | ty::Char
-            | ty::Int(_)
-            | ty::Uint(_)
-            | ty::Float(_)
-            | ty::Str
-            | ty::RawPtr(_, _)
-            | ty::Ref(_, _, _)
-            | ty::FnDef(_, _)
-            | ty::FnPtr(_)
-            | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
-            | ty::Error(_) => self.build_noop(),
-
             ty::Adt(adt_def, _) => {
                 assert!(adt_def.is_union());
-                match surface_drop_kind() {
-                    Some(SurfaceDropKind::Async) => self.build_fused_async_surface(),
-                    Some(SurfaceDropKind::Sync) => self.build_fused_sync_surface(),
-                    None => self.build_noop(),
+                match surface_drop_kind().unwrap() {
+                    SurfaceDropKind::Async => self.build_fused_async_surface(),
+                    SurfaceDropKind::Sync => self.build_fused_sync_surface(),
                 }
             }
 
-            ty::Dynamic(..) | ty::CoroutineWitness(..) | ty::Coroutine(..) | ty::Pat(..) => {
-                bug!(
-                    "Building async destructor constructor shim is not yet implemented for type: {self_ty:?}"
-                )
-            }
-
             ty::Bound(..)
             | ty::Foreign(_)
             | ty::Placeholder(_)
@@ -180,6 +161,12 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
             | ty::Alias(..) => {
                 bug!("Building async destructor for unexpected type: {self_ty:?}")
             }
+
+            _ => {
+                bug!(
+                    "Building async destructor constructor shim is not yet implemented for type: {self_ty:?}"
+                )
+            }
         }
     }
 
@@ -430,11 +417,15 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
     }
 
     fn combine_async_surface(&mut self) -> Ty<'tcx> {
-        self.apply_combinator(1, LangItem::SurfaceAsyncDropInPlace, &[self.self_ty.into()])
+        self.apply_combinator(1, LangItem::SurfaceAsyncDropInPlace, &[self.self_ty.unwrap().into()])
     }
 
     fn combine_sync_surface(&mut self) -> Ty<'tcx> {
-        self.apply_combinator(1, LangItem::AsyncDropSurfaceDropInPlace, &[self.self_ty.into()])
+        self.apply_combinator(
+            1,
+            LangItem::AsyncDropSurfaceDropInPlace,
+            &[self.self_ty.unwrap().into()],
+        )
     }
 
     fn combine_fuse(&mut self, inner_future_ty: Ty<'tcx>) -> Ty<'tcx> {
@@ -457,7 +448,7 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
         self.apply_combinator(
             4,
             LangItem::AsyncDropEither,
-            &[other.into(), matched.into(), self.self_ty.into()],
+            &[other.into(), matched.into(), self.self_ty.unwrap().into()],
         )
     }
 
@@ -477,7 +468,18 @@ impl<'tcx> AsyncDestructorCtorShimBuilder<'tcx> {
 
         debug_assert_eq!(
             output.ty(&self.locals, self.tcx),
-            self.self_ty.async_destructor_ty(self.tcx, self.param_env),
+            self.self_ty.map(|ty| ty.async_destructor_ty(self.tcx, self.param_env)).unwrap_or_else(
+                || {
+                    self.tcx
+                        .fn_sig(
+                            self.tcx.require_lang_item(LangItem::AsyncDropNoop, Some(self.span)),
+                        )
+                        .instantiate_identity()
+                        .output()
+                        .no_bound_vars()
+                        .unwrap()
+                }
+            ),
         );
         let dead_storage = match &output {
             Operand::Move(place) => Some(Statement {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 5cbf13bd9ce..a8fa6fe002d 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -966,14 +966,14 @@ fn visit_instance_use<'tcx>(
         ty::InstanceDef::ThreadLocalShim(..) => {
             bug!("{:?} being reified", instance);
         }
-        ty::InstanceDef::DropGlue(_, None) => {
+        ty::InstanceDef::DropGlue(_, None) | ty::InstanceDef::AsyncDropGlueCtorShim(_, None) => {
             // Don't need to emit noop drop glue if we are calling directly.
             if !is_direct_call {
                 output.push(create_fn_mono_item(tcx, instance, source));
             }
         }
         ty::InstanceDef::DropGlue(_, Some(_))
-        | ty::InstanceDef::AsyncDropGlueCtorShim(..)
+        | ty::InstanceDef::AsyncDropGlueCtorShim(_, Some(_))
         | ty::InstanceDef::VTableShim(..)
         | ty::InstanceDef::ReifyShim(..)
         | ty::InstanceDef::ClosureOnceShim { .. }
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 74098dccfcb..23e07890bb6 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -772,7 +772,7 @@ fn mono_item_visibility<'tcx>(
     let def_id = match instance.def {
         InstanceDef::Item(def_id)
         | InstanceDef::DropGlue(def_id, Some(_))
-        | InstanceDef::AsyncDropGlueCtorShim(def_id, _) => def_id,
+        | InstanceDef::AsyncDropGlueCtorShim(def_id, Some(_)) => def_id,
 
         // We match the visibility of statics here
         InstanceDef::ThreadLocalShim(def_id) => {
@@ -789,6 +789,7 @@ fn mono_item_visibility<'tcx>(
         | InstanceDef::ConstructCoroutineInClosureShim { .. }
         | InstanceDef::CoroutineKindShim { .. }
         | InstanceDef::DropGlue(..)
+        | InstanceDef::AsyncDropGlueCtorShim(..)
         | InstanceDef::CloneShim(..)
         | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden,
     };
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index 6a2e58bc922..e4d961a7f0c 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -819,7 +819,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
         goal: Goal<'tcx, Self>,
     ) -> QueryResult<'tcx> {
         let self_ty = goal.predicate.self_ty();
-        let discriminant_ty = match *self_ty.kind() {
+        let async_destructor_ty = match *self_ty.kind() {
             ty::Bool
             | ty::Char
             | ty::Int(..)
@@ -833,14 +833,10 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
             | ty::Closure(..)
             | ty::CoroutineClosure(..)
             | ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
-            | ty::Coroutine(..)
-            | ty::CoroutineWitness(..)
-            | ty::Pat(..)
             | ty::Never
             | ty::Adt(_, _)
             | ty::Str
             | ty::Slice(_)
-            | ty::Dynamic(_, _, _)
             | ty::Tuple(_)
             | ty::Error(_) => self_ty.async_destructor_ty(ecx.tcx(), goal.param_env),
 
@@ -858,10 +854,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                 "unexpected self ty `{:?}` when normalizing `<T as AsyncDestruct>::AsyncDestructor`",
                 goal.predicate.self_ty()
             ),
+
+            _ => bug!(
+                "`consider_builtin_async_destruct_candidate` is not yet implemented for type: {self_ty:?}"
+            ),
         };
 
         ecx.probe_misc_candidate("builtin async destruct").enter(|ecx| {
-            ecx.eq(goal.param_env, goal.predicate.term, discriminant_ty.into())
+            ecx.eq(goal.param_env, goal.predicate.term, async_destructor_ty.into())
                 .expect("expected goal term to be fully unconstrained");
             ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
         })
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 9217bf77ba6..47df11ff7f8 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1100,14 +1100,14 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
                         | ty::Infer(ty::InferTy::IntVar(_) | ty::InferTy::FloatVar(..)) => true,
 
                         // type parameters, opaques, and unnormalized projections don't have
-                        // a known discriminant and may need to be normalized further or rely
+                        // a known async destructor and may need to be normalized further or rely
                         // on param env for async destructor projections
                         ty::Param(_)
                         | ty::Foreign(_)
                         | ty::Alias(..)
                         | ty::Bound(..)
                         | ty::Placeholder(..)
-                        | ty::Infer(..)
+                        | ty::Infer(_)
                         | ty::Error(_) => false,
                     }
                 } else if lang_items.pointee_trait() == Some(trait_ref.def_id) {
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 3a18f4d0939..400556a7d6a 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -57,44 +57,25 @@ fn resolve_instance<'tcx>(
         } else if Some(def_id) == tcx.lang_items().async_drop_in_place_fn() {
             let ty = args.type_at(0);
 
-            match *ty.kind() {
-                ty::Array(..)
-                | ty::Slice(_)
-                | ty::Tuple(_)
-                | ty::Bool
-                | ty::Char
-                | ty::Int(_)
-                | ty::Uint(_)
-                | ty::Float(_)
-                | ty::Str
-                | ty::RawPtr(_, _)
-                | ty::Ref(..)
-                | ty::FnDef(..)
-                | ty::FnPtr(..)
-                | ty::Infer(ty::IntVar(_) | ty::FloatVar(_))
-                | ty::Adt(..)
-                | ty::Closure(..)
-                | ty::CoroutineClosure(..)
-                | ty::CoroutineWitness(..)
-                | ty::Pat(..)
-                | ty::Never
-                | ty::Coroutine(..) => {}
-
-                ty::Param(_)
-                | ty::Error(_)
-                | ty::Dynamic(..)
-                | ty::Alias(..)
-                | ty::Infer(ty::TyVar(_))
-                | ty::Bound(..)
-                | ty::Foreign(_)
-                | ty::Placeholder(_)
-                | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
-                    return Ok(None);
+            if ty.is_async_destructor_noop(tcx, param_env) {
+                match *ty.kind() {
+                    ty::Closure(..)
+                    | ty::CoroutineClosure(..)
+                    | ty::Coroutine(..)
+                    | ty::Tuple(..)
+                    | ty::Adt(..)
+                    | ty::Dynamic(..)
+                    | ty::Array(..)
+                    | ty::Slice(..) => {}
+                    // Async destructor ctor shims can only be built from ADTs.
+                    _ => return Ok(None),
                 }
+                debug!(" => nontrivial async drop glue ctor");
+                ty::InstanceDef::AsyncDropGlueCtorShim(def_id, Some(ty))
+            } else {
+                debug!(" => trivial async drop glue ctor");
+                ty::InstanceDef::AsyncDropGlueCtorShim(def_id, None)
             }
-
-            debug!(" =>  async drop glue ctor");
-            ty::InstanceDef::AsyncDropGlueCtorShim(def_id, ty)
         } else {
             debug!(" => free item");
             // FIXME(effects): we may want to erase the effect param if that is present on this item.