about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorAndrew Zhogin <andrew.zhogin@gmail.com>2024-08-26 16:45:15 +0300
committerAndrew Zhogin <andrew.zhogin@gmail.com>2025-04-28 16:23:13 +0700
commitc366756a8537ef998d32c1ef57098d5aae7ca92f (patch)
tree9e2bb71eee25b90a0ddee1b15ed8ba339d5f0d9e /tests
parent52c1838fa712ee60d35b0d8cb6d4df3225430176 (diff)
downloadrust-c366756a8537ef998d32c1ef57098d5aae7ca92f.tar.gz
rust-c366756a8537ef998d32c1ef57098d5aae7ca92f.zip
AsyncDrop implementation using shim codegen of async_drop_in_place::{closure}, scoped async drop added.
Diffstat (limited to 'tests')
-rw-r--r--tests/crashes/128695.rs11
-rw-r--r--tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir8
-rw-r--r--tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir8
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir8
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir8
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir8
-rw-r--r--tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir8
-rw-r--r--tests/ui/async-await/async-drop/async-drop-future-from-future.rs101
-rw-r--r--tests/ui/async-await/async-drop/async-drop-future-from-future.run.stdout5
-rw-r--r--tests/ui/async-await/async-drop/async-drop-future-in-sync-context.rs82
-rw-r--r--tests/ui/async-await/async-drop/async-drop-future-in-sync-context.run.stdout3
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue-array.rs112
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue-array.run.stdout12
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue-generic.rs111
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue-generic.run.stdout12
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue.rs124
-rw-r--r--tests/ui/async-await/async-drop/async-drop-glue.run.stdout11
-rw-r--r--tests/ui/async-await/async-drop/async-drop-initial.rs (renamed from tests/ui/async-await/async-drop.rs)149
-rw-r--r--tests/ui/async-await/async-drop/async-drop-initial.run.stdout (renamed from tests/ui/async-await/async-drop.run.stdout)0
-rw-r--r--tests/ui/async-await/async-drop/async-drop-middle-drop.rs110
-rw-r--r--tests/ui/async-await/async-drop/async-drop-middle-drop.run.stdout4
-rw-r--r--tests/ui/async-await/async-drop/async-drop-open.rs127
-rw-r--r--tests/ui/async-await/async-drop/async-drop-open.run.stdout11
-rw-r--r--tests/ui/async-await/async-drop/async-drop.rs105
-rw-r--r--tests/ui/async-await/async-drop/async-drop.run.stdout6
-rw-r--r--tests/ui/async-await/async-drop/ex-ice-132103.rs (renamed from tests/crashes/132103.rs)9
-rw-r--r--tests/ui/async-await/async-drop/ex-ice1.rs13
-rw-r--r--tests/ui/async-await/async-drop/ex-ice1.stderr19
-rw-r--r--tests/ui/feature-gates/feature-gate-async-drop.rs16
-rw-r--r--tests/ui/feature-gates/feature-gate-async-drop.stderr33
30 files changed, 1145 insertions, 89 deletions
diff --git a/tests/crashes/128695.rs b/tests/crashes/128695.rs
deleted file mode 100644
index 661f427dc0e..00000000000
--- a/tests/crashes/128695.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: rust-lang/rust#128695
-//@ edition: 2021
-
-use core::pin::{pin, Pin};
-
-fn main() {
-    let fut = pin!(async {
-        let async_drop_fut = pin!(core::future::async_drop(async {}));
-        (async_drop_fut).await;
-    });
-}
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
index 0c8a17ff70b..b43af549b23 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
@@ -68,14 +68,18 @@ yields ()
     }
 
     bb10: {
-        drop(_1) -> [return: bb11, unwind: bb12];
+        drop(_1) -> [return: bb11, unwind: bb13, drop: bb12];
     }
 
     bb11: {
         return;
     }
 
-    bb12 (cleanup): {
+    bb12: {
+        coroutine_drop;
+    }
+
+    bb13 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
index 9070c95bca4..5623b6d64e9 100644
--- a/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
@@ -51,14 +51,18 @@ yields ()
     }
 
     bb6: {
-        drop(_1) -> [return: bb7, unwind: bb8];
+        drop(_1) -> [return: bb7, unwind: bb9, drop: bb8];
     }
 
     bb7: {
         return;
     }
 
-    bb8 (cleanup): {
+    bb8: {
+        coroutine_drop;
+    }
+
+    bb9 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
index 8a584853e00..4d484b16b50 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
@@ -34,14 +34,18 @@ yields ()
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
+        drop(_1) -> [return: bb1, unwind: bb3, drop: bb2];
     }
 
     bb1: {
         return;
     }
 
-    bb2 (cleanup): {
+    bb2: {
+        coroutine_drop;
+    }
+
+    bb3 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
index c5f538e5ecd..ace780f773e 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
@@ -34,14 +34,18 @@ yields ()
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
+        drop(_1) -> [return: bb1, unwind: bb3, drop: bb2];
     }
 
     bb1: {
         return;
     }
 
-    bb2 (cleanup): {
+    bb2: {
+        coroutine_drop;
+    }
+
+    bb3 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
index c6721085eb2..f50ad689f44 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
@@ -34,14 +34,18 @@ yields ()
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
+        drop(_1) -> [return: bb1, unwind: bb3, drop: bb2];
     }
 
     bb1: {
         return;
     }
 
-    bb2 (cleanup): {
+    bb2: {
+        coroutine_drop;
+    }
+
+    bb3 (cleanup): {
         resume;
     }
 }
diff --git a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
index e295f9b3cf1..62d8adeedcb 100644
--- a/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
+++ b/tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
@@ -34,14 +34,18 @@ yields ()
         StorageDead(_5);
         StorageDead(_4);
         StorageDead(_3);
-        drop(_1) -> [return: bb1, unwind: bb2];
+        drop(_1) -> [return: bb1, unwind: bb3, drop: bb2];
     }
 
     bb1: {
         return;
     }
 
-    bb2 (cleanup): {
+    bb2: {
+        coroutine_drop;
+    }
+
+    bb3 (cleanup): {
         resume;
     }
 }
diff --git a/tests/ui/async-await/async-drop/async-drop-future-from-future.rs b/tests/ui/async-await/async-drop/async-drop-future-from-future.rs
new file mode 100644
index 00000000000..44dcbd14f48
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-future-from-future.rs
@@ -0,0 +1,101 @@
+//@ run-pass
+//@ check-run-results
+// Future `bar` with internal async drop `Foo` will have async drop itself.
+// And we trying to drop this future in sync context (`block_on` func)
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        println!("Foo::new({})", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("Foo::drop({})", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("Foo::async drop({})", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    block_on(bar(10));
+    println!("done")
+}
+
+async fn baz(ident_base: usize) {
+    let mut _first = Foo::new(ident_base);
+}
+
+async fn bar(ident_base: usize) {
+    let mut _first = Foo::new(ident_base);
+    baz(ident_base + 1).await;
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-future-from-future.run.stdout b/tests/ui/async-await/async-drop/async-drop-future-from-future.run.stdout
new file mode 100644
index 00000000000..c2663b3f238
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-future-from-future.run.stdout
@@ -0,0 +1,5 @@
+Foo::new(10)
+Foo::new(11)
+Foo::async drop(11)
+Foo::async drop(10)
+done
diff --git a/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.rs b/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.rs
new file mode 100644
index 00000000000..417dce62dba
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.rs
@@ -0,0 +1,82 @@
+//@ run-pass
+//@ check-run-results
+// Future `bar` with internal async drop `Foo` will have async drop itself.
+// And we trying to drop this future in sync context (`block_on` func)
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+//@ edition: 2021
+
+use std::{
+    future::{Future, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        println!("Foo::new({})", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("Foo::drop({})", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("Foo::async drop({})", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    block_on(bar(10));
+    println!("done")
+}
+
+async fn bar(ident_base: usize) {
+    let mut _first = Foo::new(ident_base);
+}
+
+fn block_on<F>(fut: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut = pin!(fut);
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.run.stdout b/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.run.stdout
new file mode 100644
index 00000000000..ad0b083ca09
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-future-in-sync-context.run.stdout
@@ -0,0 +1,3 @@
+Foo::new(10)
+Foo::async drop(10)
+done
diff --git a/tests/ui/async-await/async-drop/async-drop-glue-array.rs b/tests/ui/async-await/async-drop/async-drop-glue-array.rs
new file mode 100644
index 00000000000..21c08da2337
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue-array.rs
@@ -0,0 +1,112 @@
+//@ run-pass
+//@ check-run-results
+// struct `Foo` has both sync and async drop.
+// Struct `Complex` contains three `Foo` fields and has complex async drop glue.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+#[inline(never)]
+fn myprintln(msg: &str, my_resource_handle: usize) {
+    println!("{} : {}", msg, my_resource_handle);
+}
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        myprintln("Foo::new()", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        myprintln("Foo::drop()", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        myprintln("Foo::async drop()", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    {
+        let _ = Foo::new(7);
+    }
+    println!("Middle");
+    {
+        block_on(bar(10));
+    }
+    println!("Done")
+}
+
+async fn bar(ident_base: usize) {
+    let _vec: [Foo; 4] = [
+        Foo::new(ident_base),
+        Foo::new(ident_base + 1),
+        Foo::new(ident_base + 2),
+        Foo::new(ident_base + 3)
+    ];
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-glue-array.run.stdout b/tests/ui/async-await/async-drop/async-drop-glue-array.run.stdout
new file mode 100644
index 00000000000..56b61103cc4
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue-array.run.stdout
@@ -0,0 +1,12 @@
+Foo::new() : 7
+Foo::drop() : 7
+Middle
+Foo::new() : 10
+Foo::new() : 11
+Foo::new() : 12
+Foo::new() : 13
+Foo::async drop() : 10
+Foo::async drop() : 11
+Foo::async drop() : 12
+Foo::async drop() : 13
+Done
diff --git a/tests/ui/async-await/async-drop/async-drop-glue-generic.rs b/tests/ui/async-await/async-drop/async-drop-glue-generic.rs
new file mode 100644
index 00000000000..9e8ae130324
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue-generic.rs
@@ -0,0 +1,111 @@
+//@ run-pass
+//@ check-run-results
+// struct `Foo` has both sync and async drop.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+#[inline(never)]
+fn myprintln(msg: &str, my_resource_handle: usize) {
+    println!("{} : {}", msg, my_resource_handle);
+}
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        myprintln("Foo::new()", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        myprintln("Foo::drop()", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        myprintln("Foo::async drop()", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    {
+        let _ = Foo::new(7);
+    }
+    println!("Middle");
+    {
+        block_on(bar(6, 10));
+    }
+    println!("Done")
+}
+
+async fn bar<T>(_arg: T, ident_base: usize) {
+    let _vec: [Foo; 4] = [
+        Foo::new(ident_base),
+        Foo::new(ident_base + 1),
+        Foo::new(ident_base + 2),
+        Foo::new(ident_base + 3)
+    ];
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-glue-generic.run.stdout b/tests/ui/async-await/async-drop/async-drop-glue-generic.run.stdout
new file mode 100644
index 00000000000..56b61103cc4
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue-generic.run.stdout
@@ -0,0 +1,12 @@
+Foo::new() : 7
+Foo::drop() : 7
+Middle
+Foo::new() : 10
+Foo::new() : 11
+Foo::new() : 12
+Foo::new() : 13
+Foo::async drop() : 10
+Foo::async drop() : 11
+Foo::async drop() : 12
+Foo::async drop() : 13
+Done
diff --git a/tests/ui/async-await/async-drop/async-drop-glue.rs b/tests/ui/async-await/async-drop/async-drop-glue.rs
new file mode 100644
index 00000000000..dc4bb527a51
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue.rs
@@ -0,0 +1,124 @@
+//@ run-pass
+//@ check-run-results
+// struct `Foo` has both sync and async drop.
+// Struct `Complex` contains three `Foo` fields and has complex async drop glue.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+#[inline(never)]
+fn myprintln(msg: &str, my_resource_handle: usize) {
+    println!("{} : {}", msg, my_resource_handle);
+}
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+#[allow(dead_code)]
+struct Complex {
+    field1: Foo,
+    field2: Foo,
+    field3: Foo,
+}
+
+impl Complex {
+    fn new(my_resource_handle: usize) -> Self {
+        myprintln("Complex::new()", my_resource_handle);
+        let field1 = Foo::new(my_resource_handle);
+        let field2 = Foo::new(my_resource_handle + 1);
+        let field3 = Foo::new(my_resource_handle + 2);
+        Complex { field1, field2, field3 }
+    }
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        myprintln("Foo::new()", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        myprintln("Foo::drop()", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        myprintln("Foo::async drop()", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    {
+        let _ = Foo::new(7);
+    }
+    println!("Middle");
+    {
+        block_on(bar(10));
+    }
+    println!("Done")
+}
+
+async fn bar(ident_base: usize) {
+    let _complex = Complex::new(ident_base);
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-glue.run.stdout b/tests/ui/async-await/async-drop/async-drop-glue.run.stdout
new file mode 100644
index 00000000000..e21a9dd34fa
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-glue.run.stdout
@@ -0,0 +1,11 @@
+Foo::new() : 7
+Foo::drop() : 7
+Middle
+Complex::new() : 10
+Foo::new() : 10
+Foo::new() : 11
+Foo::new() : 12
+Foo::async drop() : 10
+Foo::async drop() : 11
+Foo::async drop() : 12
+Done
diff --git a/tests/ui/async-await/async-drop.rs b/tests/ui/async-await/async-drop/async-drop-initial.rs
index b1af81423ce..80b34840c8b 100644
--- a/tests/ui/async-await/async-drop.rs
+++ b/tests/ui/async-await/async-drop/async-drop-initial.rs
@@ -52,21 +52,20 @@ fn main() {
 
     let i = 13;
     let fut = pin!(async {
-        test_async_drop(Int(0), 0).await;
-        // FIXME(#63818): niches in coroutines are disabled.
-        // Some of these sizes should be smaller, as indicated in comments.
-        test_async_drop(AsyncInt(0), /*104*/ 112).await;
-        test_async_drop([AsyncInt(1), AsyncInt(2)], /*152*/ 168).await;
-        test_async_drop((AsyncInt(3), AsyncInt(4)), /*488*/ 528).await;
-        test_async_drop(5, 0).await;
+        test_async_drop(Int(0), 16).await;
+        test_async_drop(AsyncInt(0), 32).await;
+        test_async_drop([AsyncInt(1), AsyncInt(2)], 104).await;
+        test_async_drop((AsyncInt(3), AsyncInt(4)), 120).await;
+        test_async_drop(5, 16).await;
         let j = 42;
-        test_async_drop(&i, 0).await;
-        test_async_drop(&j, 0).await;
-        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, /*1688*/ 1792).await;
-        test_async_drop(ManuallyDrop::new(AsyncInt(9)), 0).await;
+        test_async_drop(&i, 16).await;
+        test_async_drop(&j, 16).await;
+        test_async_drop(AsyncStruct { b: AsyncInt(8), a: AsyncInt(7), i: 6 }, 168).await;
+        test_async_drop(ManuallyDrop::new(AsyncInt(9)), 16).await;
 
         let foo = AsyncInt(10);
-        test_async_drop(AsyncReference { foo: &foo }, /*104*/ 112).await;
+        test_async_drop(AsyncReference { foo: &foo }, 32).await;
+        let _ = ManuallyDrop::new(foo);
 
         let foo = AsyncInt(11);
         test_async_drop(
@@ -75,21 +74,22 @@ fn main() {
                 let foo = AsyncInt(10);
                 foo
             },
-            /*120*/ 136,
+            48,
         )
         .await;
 
-        test_async_drop(AsyncEnum::A(AsyncInt(12)), /*680*/ 736).await;
-        test_async_drop(AsyncEnum::B(SyncInt(13)), /*680*/ 736).await;
+        test_async_drop(AsyncEnum::A(AsyncInt(12)), 104).await;
+        test_async_drop(AsyncEnum::B(SyncInt(13)), 104).await;
 
-        test_async_drop(SyncInt(14), /*16*/ 24).await;
+        test_async_drop(SyncInt(14), 16).await;
         test_async_drop(
             SyncThenAsync { i: 15, a: AsyncInt(16), b: SyncInt(17), c: AsyncInt(18) },
-            /*3064*/ 3296,
+            120,
         )
         .await;
 
-        let async_drop_fut = pin!(core::future::async_drop(AsyncInt(19)));
+        let mut ptr19 = mem::MaybeUninit::new(AsyncInt(19));
+        let async_drop_fut = pin!(unsafe { async_drop_in_place(ptr19.as_mut_ptr()) });
         test_idempotency(async_drop_fut).await;
 
         let foo = AsyncInt(20);
@@ -101,11 +101,11 @@ fn main() {
                 black_box(core::future::ready(())).await;
                 foo
             },
-            /*120*/ 136,
+            48,
         )
         .await;
 
-        test_async_drop(AsyncUnion { signed: 21 }, /*32*/ 40).await;
+        test_async_drop(AsyncUnion { signed: 21 }, 32).await;
     });
     let res = fut.poll(&mut cx);
     assert_eq!(res, Poll::Ready(()));
@@ -113,13 +113,14 @@ fn main() {
 
 struct AsyncInt(i32);
 
+impl Drop for AsyncInt {
+    fn drop(&mut self) {
+        println!("AsyncInt::drop: {}", self.0);
+    }
+}
 impl AsyncDrop for AsyncInt {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncInt::Dropper::poll: {}", self.0);
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncInt::Dropper::poll: {}", self.0);
     }
 }
 
@@ -148,13 +149,15 @@ struct AsyncReference<'a> {
     foo: &'a AsyncInt,
 }
 
-impl AsyncDrop for AsyncReference<'_> {
-    type Dropper<'a> = impl Future<Output = ()> where Self: 'a;
+impl Drop for AsyncReference<'_> {
+    fn drop(&mut self) {
+        println!("AsyncReference::drop: {}", self.foo.0);
+    }
+}
 
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncReference::Dropper::poll: {}", self.foo.0);
-        }
+impl AsyncDrop for AsyncReference<'_> {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncReference::Dropper::poll: {}", self.foo.0);
     }
 }
 
@@ -166,13 +169,15 @@ struct AsyncStruct {
     b: AsyncInt,
 }
 
-impl AsyncDrop for AsyncStruct {
-    type Dropper<'a> = impl Future<Output = ()>;
+impl Drop for AsyncStruct {
+    fn drop(&mut self) {
+        println!("AsyncStruct::drop: {}", self.i);
+    }
+}
 
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!("AsyncStruct::Dropper::poll: {}", self.i);
-        }
+impl AsyncDrop for AsyncStruct {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("AsyncStruct::Dropper::poll: {}", self.i);
     }
 }
 
@@ -181,23 +186,34 @@ enum AsyncEnum {
     B(SyncInt),
 }
 
+impl Drop for AsyncEnum {
+    fn drop(&mut self) {
+        let new_self = match self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::drop: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::drop: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
+    }
+}
 impl AsyncDrop for AsyncEnum {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(mut self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            let new_self = match &*self {
-                AsyncEnum::A(foo) => {
-                    println!("AsyncEnum(A)::Dropper::poll: {}", foo.0);
-                    AsyncEnum::B(SyncInt(foo.0))
-                }
-                AsyncEnum::B(foo) => {
-                    println!("AsyncEnum(B)::Dropper::poll: {}", foo.0);
-                    AsyncEnum::A(AsyncInt(foo.0))
-                }
-            };
-            mem::forget(mem::replace(&mut *self, new_self));
-        }
+    async fn drop(mut self: Pin<&mut Self>) {
+        let new_self = match &*self {
+            AsyncEnum::A(foo) => {
+                println!("AsyncEnum(A)::Dropper::poll: {}", foo.0);
+                AsyncEnum::B(SyncInt(foo.0))
+            }
+            AsyncEnum::B(foo) => {
+                println!("AsyncEnum(B)::Dropper::poll: {}", foo.0);
+                AsyncEnum::A(AsyncInt(foo.0))
+            }
+        };
+        mem::forget(mem::replace(&mut *self, new_self));
     }
 }
 
@@ -207,16 +223,21 @@ union AsyncUnion {
     unsigned: u32,
 }
 
+impl Drop for AsyncUnion {
+    fn drop(&mut self) {
+        println!(
+            "AsyncUnion::drop: {}, {}",
+            unsafe { self.signed },
+            unsafe { self.unsigned },
+        );
+    }
+}
 impl AsyncDrop for AsyncUnion {
-    type Dropper<'a> = impl Future<Output = ()>;
-
-    fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_> {
-        async move {
-            println!(
-                "AsyncUnion::Dropper::poll: {}, {}",
-                unsafe { self.signed },
-                unsafe { self.unsigned },
-            );
-        }
+    async fn drop(self: Pin<&mut Self>) {
+        println!(
+            "AsyncUnion::Dropper::poll: {}, {}",
+            unsafe { self.signed },
+            unsafe { self.unsigned },
+        );
     }
 }
diff --git a/tests/ui/async-await/async-drop.run.stdout b/tests/ui/async-await/async-drop/async-drop-initial.run.stdout
index 9cae4331caf..9cae4331caf 100644
--- a/tests/ui/async-await/async-drop.run.stdout
+++ b/tests/ui/async-await/async-drop/async-drop-initial.run.stdout
diff --git a/tests/ui/async-await/async-drop/async-drop-middle-drop.rs b/tests/ui/async-await/async-drop/async-drop-middle-drop.rs
new file mode 100644
index 00000000000..772a853fe1e
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-middle-drop.rs
@@ -0,0 +1,110 @@
+//@ run-pass
+//@ check-run-results
+// Test async drop of coroutine `bar` (with internal async drop),
+// stopped at the middle of execution, with AsyncDrop object Foo active.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+//@ edition: 2021
+
+use std::mem::ManuallyDrop;
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        println!("Foo::new({})", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        println!("Foo::drop({})", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        println!("Foo::async drop({})", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    block_on_and_drop_in_the_middle(bar(10));
+    println!("done")
+}
+
+pub struct MiddleFuture {
+    first_call: bool,
+}
+impl Future for MiddleFuture {
+    type Output = ();
+    fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
+        if self.first_call {
+            println!("MiddleFuture first poll");
+            self.first_call = false;
+            Poll::Pending
+        } else {
+            println!("MiddleFuture Ready");
+            Poll::Ready(())
+        }
+    }
+}
+
+async fn bar(ident_base: usize) {
+    let middle = MiddleFuture { first_call: true };
+    let mut _first = Foo::new(ident_base);
+    middle.await; // Hanging `bar` future before Foo drop
+}
+
+fn block_on_and_drop_in_the_middle<F>(fut_unpin: F) -> F::Output
+where
+    F: Future<Output = ()>,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let poll1 = fut.as_mut().poll(&mut context);
+    assert!(poll1.is_pending());
+
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-middle-drop.run.stdout b/tests/ui/async-await/async-drop/async-drop-middle-drop.run.stdout
new file mode 100644
index 00000000000..60df7674d0a
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-middle-drop.run.stdout
@@ -0,0 +1,4 @@
+Foo::new(10)
+MiddleFuture first poll
+Foo::async drop(10)
+done
diff --git a/tests/ui/async-await/async-drop/async-drop-open.rs b/tests/ui/async-await/async-drop/async-drop-open.rs
new file mode 100644
index 00000000000..d14eff874ae
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-open.rs
@@ -0,0 +1,127 @@
+//@ run-pass
+//@ check-run-results
+// struct `Foo` has both sync and async drop.
+// Struct `Complex` contains three `Foo` fields and one of them is moved out.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+#[inline(never)]
+fn myprintln(msg: &str, my_resource_handle: usize) {
+    println!("{} : {}", msg, my_resource_handle);
+}
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+#[allow(dead_code)]
+struct Complex {
+    field1: Foo,
+    field2: Foo,
+    field3: Foo,
+}
+
+impl Complex {
+    fn new(my_resource_handle: usize) -> Self {
+        myprintln("Complex::new()", my_resource_handle);
+        let field1 = Foo::new(my_resource_handle);
+        let field2 = Foo::new(my_resource_handle + 1);
+        let field3 = Foo::new(my_resource_handle + 2);
+        Complex { field1, field2, field3 }
+    }
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        myprintln("Foo::new()", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        myprintln("Foo::drop()", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        myprintln("Foo::async drop()", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    {
+        let _ = Foo::new(7);
+    }
+    println!("Middle");
+    // Inside field1 and field3 of Complex must be dropped (as async drop)
+    // field2 must be dropped here (as sync drop)
+    {
+        let _field2 = block_on(bar(10));
+    }
+    println!("Done")
+}
+
+async fn bar(ident_base: usize) -> Foo {
+    let complex = Complex::new(ident_base);
+    complex.field2
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop-open.run.stdout b/tests/ui/async-await/async-drop/async-drop-open.run.stdout
new file mode 100644
index 00000000000..e72dfd8a743
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop-open.run.stdout
@@ -0,0 +1,11 @@
+Foo::new() : 7
+Foo::drop() : 7
+Middle
+Complex::new() : 10
+Foo::new() : 10
+Foo::new() : 11
+Foo::new() : 12
+Foo::async drop() : 10
+Foo::async drop() : 12
+Foo::drop() : 11
+Done
diff --git a/tests/ui/async-await/async-drop/async-drop.rs b/tests/ui/async-await/async-drop/async-drop.rs
new file mode 100644
index 00000000000..2d9c5934be5
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop.rs
@@ -0,0 +1,105 @@
+//@ run-pass
+//@ check-run-results
+// struct `Foo` has both sync and async drop.
+// Sync version is called in sync context, async version is called in async function.
+
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
+use std::mem::ManuallyDrop;
+
+//@ edition: 2021
+
+#[inline(never)]
+fn myprintln(msg: &str, my_resource_handle: usize) {
+    println!("{} : {}", msg, my_resource_handle);
+}
+
+use std::{
+    future::{Future, async_drop_in_place, AsyncDrop},
+    pin::{pin, Pin},
+    sync::{mpsc, Arc},
+    task::{Context, Poll, Wake, Waker},
+};
+
+struct Foo {
+    my_resource_handle: usize,
+}
+
+impl Foo {
+    fn new(my_resource_handle: usize) -> Self {
+        let out = Foo {
+            my_resource_handle,
+        };
+        myprintln("Foo::new()", my_resource_handle);
+        out
+    }
+}
+
+impl Drop for Foo {
+    fn drop(&mut self) {
+        myprintln("Foo::drop()", self.my_resource_handle);
+    }
+}
+
+impl AsyncDrop for Foo {
+    async fn drop(self: Pin<&mut Self>) {
+        myprintln("Foo::async drop()", self.my_resource_handle);
+    }
+}
+
+fn main() {
+    {
+        let _ = Foo::new(7);
+    }
+    println!("Middle");
+    block_on(bar(10));
+    println!("Done")
+}
+
+async fn bar(ident_base: usize) {
+    let mut _first = Foo::new(ident_base);
+}
+
+fn block_on<F>(fut_unpin: F) -> F::Output
+where
+    F: Future,
+{
+    let mut fut_pin = pin!(ManuallyDrop::new(fut_unpin));
+    let mut fut: Pin<&mut F> = unsafe {
+        Pin::map_unchecked_mut(fut_pin.as_mut(), |x| &mut **x)
+    };
+    let (waker, rx) = simple_waker();
+    let mut context = Context::from_waker(&waker);
+    let rv = loop {
+        match fut.as_mut().poll(&mut context) {
+            Poll::Ready(out) => break out,
+            // expect wake in polls
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    };
+    let drop_fut_unpin = unsafe { async_drop_in_place(fut.get_unchecked_mut()) };
+    let mut drop_fut: Pin<&mut _> = pin!(drop_fut_unpin);
+    loop {
+        match drop_fut.as_mut().poll(&mut context) {
+            Poll::Ready(()) => break,
+            Poll::Pending => rx.try_recv().unwrap(),
+        }
+    }
+    rv
+}
+
+fn simple_waker() -> (Waker, mpsc::Receiver<()>) {
+    struct SimpleWaker {
+        tx: std::sync::mpsc::Sender<()>,
+    }
+
+    impl Wake for SimpleWaker {
+        fn wake(self: Arc<Self>) {
+            self.tx.send(()).unwrap();
+        }
+    }
+
+    let (tx, rx) = mpsc::channel();
+    (Waker::from(Arc::new(SimpleWaker { tx })), rx)
+}
diff --git a/tests/ui/async-await/async-drop/async-drop.run.stdout b/tests/ui/async-await/async-drop/async-drop.run.stdout
new file mode 100644
index 00000000000..cb7d0b0fea5
--- /dev/null
+++ b/tests/ui/async-await/async-drop/async-drop.run.stdout
@@ -0,0 +1,6 @@
+Foo::new() : 7
+Foo::drop() : 7
+Middle
+Foo::new() : 10
+Foo::async drop() : 10
+Done
diff --git a/tests/crashes/132103.rs b/tests/ui/async-await/async-drop/ex-ice-132103.rs
index e2d8378efe6..3d32cb14fb0 100644
--- a/tests/crashes/132103.rs
+++ b/tests/ui/async-await/async-drop/ex-ice-132103.rs
@@ -1,6 +1,11 @@
-//@ known-bug: #132103
+//@ run-pass
+//! This test used to ICE: rust-lang/rust#132103
+//! Fixed when re-work async drop to shim drop glue coroutine scheme.
 //@ compile-flags: -Zvalidate-mir -Zinline-mir=yes
 //@ edition: 2018
+#![feature(async_drop)]
+#![allow(incomplete_features)]
+
 use core::future::{async_drop_in_place, Future};
 use core::mem::{self};
 use core::pin::pin;
@@ -18,5 +23,5 @@ fn main() {
     let fut = pin!(async {
         test_async_drop(test_async_drop(0)).await;
     });
-    fut.poll(&mut cx);
+    let _ = fut.poll(&mut cx);
 }
diff --git a/tests/ui/async-await/async-drop/ex-ice1.rs b/tests/ui/async-await/async-drop/ex-ice1.rs
new file mode 100644
index 00000000000..f514c57097a
--- /dev/null
+++ b/tests/ui/async-await/async-drop/ex-ice1.rs
@@ -0,0 +1,13 @@
+//! This test used to ICE: rust-lang/rust#128695
+//! Fixed when re-work async drop to shim drop glue coroutine scheme.
+//@ edition: 2021
+
+use core::pin::{pin, Pin};
+
+fn main() {
+    let fut = pin!(async {
+        let async_drop_fut = pin!(core::future::async_drop(async {})); //~ ERROR: expected function, found module `core::future::async_drop`
+        //~^ ERROR: module `async_drop` is private
+        (async_drop_fut).await;
+    });
+}
diff --git a/tests/ui/async-await/async-drop/ex-ice1.stderr b/tests/ui/async-await/async-drop/ex-ice1.stderr
new file mode 100644
index 00000000000..68533edeb08
--- /dev/null
+++ b/tests/ui/async-await/async-drop/ex-ice1.stderr
@@ -0,0 +1,19 @@
+error[E0423]: expected function, found module `core::future::async_drop`
+  --> $DIR/ex-ice1.rs:9:35
+   |
+LL |         let async_drop_fut = pin!(core::future::async_drop(async {}));
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^ not a function
+
+error[E0603]: module `async_drop` is private
+  --> $DIR/ex-ice1.rs:9:49
+   |
+LL |         let async_drop_fut = pin!(core::future::async_drop(async {}));
+   |                                                 ^^^^^^^^^^ private module
+   |
+note: the module `async_drop` is defined here
+  --> $SRC_DIR/core/src/future/mod.rs:LL:COL
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0603.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/feature-gates/feature-gate-async-drop.rs b/tests/ui/feature-gates/feature-gate-async-drop.rs
new file mode 100644
index 00000000000..20511b1d8ee
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-drop.rs
@@ -0,0 +1,16 @@
+//@ edition: 2021
+
+use std::future::AsyncDrop; //~ ERROR  use of unstable library feature `async_drop`
+use std::pin::Pin;
+
+struct Foo {}
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+impl AsyncDrop for Foo { //~ ERROR  use of unstable library feature `async_drop`
+    async fn drop(self: Pin<&mut Self>) {} //~ ERROR  use of unstable library feature `async_drop`
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-async-drop.stderr b/tests/ui/feature-gates/feature-gate-async-drop.stderr
new file mode 100644
index 00000000000..e795c3a3422
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-async-drop.stderr
@@ -0,0 +1,33 @@
+error[E0658]: use of unstable library feature `async_drop`
+  --> $DIR/feature-gate-async-drop.rs:3:5
+   |
+LL | use std::future::AsyncDrop;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #126482 <https://github.com/rust-lang/rust/issues/126482> for more information
+   = help: add `#![feature(async_drop)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `async_drop`
+  --> $DIR/feature-gate-async-drop.rs:13:5
+   |
+LL |     async fn drop(self: Pin<&mut Self>) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #126482 <https://github.com/rust-lang/rust/issues/126482> for more information
+   = help: add `#![feature(async_drop)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: use of unstable library feature `async_drop`
+  --> $DIR/feature-gate-async-drop.rs:12:6
+   |
+LL | impl AsyncDrop for Foo {
+   |      ^^^^^^^^^
+   |
+   = note: see issue #126482 <https://github.com/rust-lang/rust/issues/126482> for more information
+   = help: add `#![feature(async_drop)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.