AsyncDrop implementation using shim codegen of async_drop_in_place::{closure}, scoped async drop added.
This commit is contained in:
parent
52c1838fa7
commit
c366756a85
116 changed files with 4054 additions and 1879 deletions
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
101
tests/ui/async-await/async-drop/async-drop-future-from-future.rs
Normal file
101
tests/ui/async-await/async-drop/async-drop-future-from-future.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
Foo::new(10)
|
||||
Foo::new(11)
|
||||
Foo::async drop(11)
|
||||
Foo::async drop(10)
|
||||
done
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Foo::new(10)
|
||||
Foo::async drop(10)
|
||||
done
|
||||
112
tests/ui/async-await/async-drop/async-drop-glue-array.rs
Normal file
112
tests/ui/async-await/async-drop/async-drop-glue-array.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
111
tests/ui/async-await/async-drop/async-drop-glue-generic.rs
Normal file
111
tests/ui/async-await/async-drop/async-drop-glue-generic.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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
|
||||
124
tests/ui/async-await/async-drop/async-drop-glue.rs
Normal file
124
tests/ui/async-await/async-drop/async-drop-glue.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
11
tests/ui/async-await/async-drop/async-drop-glue.run.stdout
Normal file
11
tests/ui/async-await/async-drop/async-drop-glue.run.stdout
Normal file
|
|
@ -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
|
||||
|
|
@ -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 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 },
|
||||
);
|
||||
}
|
||||
impl Drop for AsyncUnion {
|
||||
fn drop(&mut self) {
|
||||
println!(
|
||||
"AsyncUnion::drop: {}, {}",
|
||||
unsafe { self.signed },
|
||||
unsafe { self.unsigned },
|
||||
);
|
||||
}
|
||||
}
|
||||
impl AsyncDrop for AsyncUnion {
|
||||
async fn drop(self: Pin<&mut Self>) {
|
||||
println!(
|
||||
"AsyncUnion::Dropper::poll: {}, {}",
|
||||
unsafe { self.signed },
|
||||
unsafe { self.unsigned },
|
||||
);
|
||||
}
|
||||
}
|
||||
110
tests/ui/async-await/async-drop/async-drop-middle-drop.rs
Normal file
110
tests/ui/async-await/async-drop/async-drop-middle-drop.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
Foo::new(10)
|
||||
MiddleFuture first poll
|
||||
Foo::async drop(10)
|
||||
done
|
||||
127
tests/ui/async-await/async-drop/async-drop-open.rs
Normal file
127
tests/ui/async-await/async-drop/async-drop-open.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
11
tests/ui/async-await/async-drop/async-drop-open.run.stdout
Normal file
11
tests/ui/async-await/async-drop/async-drop-open.run.stdout
Normal file
|
|
@ -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
|
||||
105
tests/ui/async-await/async-drop/async-drop.rs
Normal file
105
tests/ui/async-await/async-drop/async-drop.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
6
tests/ui/async-await/async-drop/async-drop.run.stdout
Normal file
6
tests/ui/async-await/async-drop/async-drop.run.stdout
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
Foo::new() : 7
|
||||
Foo::drop() : 7
|
||||
Middle
|
||||
Foo::new() : 10
|
||||
Foo::async drop() : 10
|
||||
Done
|
||||
|
|
@ -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);
|
||||
}
|
||||
13
tests/ui/async-await/async-drop/ex-ice1.rs
Normal file
13
tests/ui/async-await/async-drop/ex-ice1.rs
Normal file
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
19
tests/ui/async-await/async-drop/ex-ice1.stderr
Normal file
19
tests/ui/async-await/async-drop/ex-ice1.stderr
Normal file
|
|
@ -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`.
|
||||
16
tests/ui/feature-gates/feature-gate-async-drop.rs
Normal file
16
tests/ui/feature-gates/feature-gate-async-drop.rs
Normal file
|
|
@ -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() {}
|
||||
33
tests/ui/feature-gates/feature-gate-async-drop.stderr
Normal file
33
tests/ui/feature-gates/feature-gate-async-drop.stderr
Normal file
|
|
@ -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`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue