mirror of
				https://github.com/rust-lang/rust.git
				synced 2025-10-31 04:57:19 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			102 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			102 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
| //@ 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)
 | |
| }
 | 
