1#![unstable(feature = "async_drop", issue = "none")]
2
3use crate::fmt;
4use crate::future::{Future, IntoFuture};
5use crate::intrinsics::discriminant_value;
6use crate::marker::{DiscriminantKind, PhantomPinned};
7use crate::mem::MaybeUninit;
8use crate::pin::Pin;
9use crate::task::{ready, Context, Poll};
10
11/// Asynchronously drops a value by running `AsyncDrop::async_drop`
12/// on a value and its fields recursively.
13#[unstable(feature = "async_drop", issue = "none")]
14pub fn async_drop<T>(value: T) -> AsyncDropOwning<T> {
15 AsyncDropOwning { value: MaybeUninit::new(val:value), dtor: None, _pinned: PhantomPinned }
16}
17
18/// A future returned by the [`async_drop`].
19#[unstable(feature = "async_drop", issue = "none")]
20pub struct AsyncDropOwning<T> {
21 value: MaybeUninit<T>,
22 dtor: Option<AsyncDropInPlace<T>>,
23 _pinned: PhantomPinned,
24}
25
26#[unstable(feature = "async_drop", issue = "none")]
27impl<T> fmt::Debug for AsyncDropOwning<T> {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 f.debug_struct(name:"AsyncDropOwning").finish_non_exhaustive()
30 }
31}
32
33#[unstable(feature = "async_drop", issue = "none")]
34impl<T> Future for AsyncDropOwning<T> {
35 type Output = ();
36
37 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
38 // SAFETY: Self is pinned thus it is ok to store references to self
39 unsafe {
40 let this: &mut AsyncDropOwning = self.get_unchecked_mut();
41 let dtor: Pin<&mut AsyncDropInPlace<…>> = Pin::new_unchecked(
42 pointer:this.dtor.get_or_insert_with(|| async_drop_in_place(to_drop:this.value.as_mut_ptr())),
43 );
44 // AsyncDestuctors are idempotent so Self gets idempotency as well
45 dtor.poll(cx)
46 }
47 }
48}
49
50#[lang = "async_drop_in_place"]
51#[allow(unconditional_recursion)]
52// FIXME: Consider if `#[rustc_diagnostic_item = "ptr_drop_in_place"]` is needed?
53unsafe fn async_drop_in_place_raw<T: ?Sized>(
54 to_drop: *mut T,
55) -> <T as AsyncDestruct>::AsyncDestructor {
56 // Code here does not matter - this is replaced by the
57 // real async drop glue constructor by the compiler.
58
59 // SAFETY: see comment above
60 unsafe { async_drop_in_place_raw(to_drop) }
61}
62
63/// Creates the asynchronous destructor of the pointed-to value.
64///
65/// # Safety
66///
67/// Behavior is undefined if any of the following conditions are violated:
68///
69/// * `to_drop` must be [valid](crate::ptr#safety) for both reads and writes.
70///
71/// * `to_drop` must be properly aligned, even if `T` has size 0.
72///
73/// * `to_drop` must be nonnull, even if `T` has size 0.
74///
75/// * The value `to_drop` points to must be valid for async dropping,
76/// which may mean it must uphold additional invariants. These
77/// invariants depend on the type of the value being dropped. For
78/// instance, when dropping a Box, the box's pointer to the heap must
79/// be valid.
80///
81/// * While `async_drop_in_place` is executing or the returned async
82/// destructor is alive, the only way to access parts of `to_drop`
83/// is through the `self: Pin<&mut Self>` references supplied to
84/// the `AsyncDrop::async_drop` methods that `async_drop_in_place`
85/// or `AsyncDropInPlace<T>::poll` invokes. This usually means the
86/// returned future stores the `to_drop` pointer and user is required
87/// to guarantee that dropped value doesn't move.
88///
89#[unstable(feature = "async_drop", issue = "none")]
90pub unsafe fn async_drop_in_place<T: ?Sized>(to_drop: *mut T) -> AsyncDropInPlace<T> {
91 // SAFETY: `async_drop_in_place_raw` has the same safety requirements
92 unsafe { AsyncDropInPlace(async_drop_in_place_raw(to_drop)) }
93}
94
95/// A future returned by the [`async_drop_in_place`].
96#[unstable(feature = "async_drop", issue = "none")]
97pub struct AsyncDropInPlace<T: ?Sized>(<T as AsyncDestruct>::AsyncDestructor);
98
99#[unstable(feature = "async_drop", issue = "none")]
100impl<T: ?Sized> fmt::Debug for AsyncDropInPlace<T> {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 f.debug_struct(name:"AsyncDropInPlace").finish_non_exhaustive()
103 }
104}
105
106#[unstable(feature = "async_drop", issue = "none")]
107impl<T: ?Sized> Future for AsyncDropInPlace<T> {
108 type Output = ();
109
110 #[inline(always)]
111 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
112 // SAFETY: This code simply forwards poll call to the inner future
113 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) }.poll(cx)
114 }
115}
116
117// FIXME(zetanumbers): Add same restrictions on AsyncDrop impls as
118// with Drop impls
119/// Custom code within the asynchronous destructor.
120#[unstable(feature = "async_drop", issue = "none")]
121#[lang = "async_drop"]
122pub trait AsyncDrop {
123 /// A future returned by the [`AsyncDrop::async_drop`] to be part
124 /// of the async destructor.
125 #[unstable(feature = "async_drop", issue = "none")]
126 type Dropper<'a>: Future<Output = ()>
127 where
128 Self: 'a;
129
130 /// Constructs the asynchronous destructor for this type.
131 #[unstable(feature = "async_drop", issue = "none")]
132 fn async_drop(self: Pin<&mut Self>) -> Self::Dropper<'_>;
133}
134
135#[lang = "async_destruct"]
136#[rustc_deny_explicit_impl(implement_via_object = false)]
137trait AsyncDestruct {
138 type AsyncDestructor: Future<Output = ()>;
139}
140
141/// Basically calls `AsyncDrop::async_drop` with pointer. Used to simplify
142/// generation of the code for `async_drop_in_place_raw`
143#[lang = "surface_async_drop_in_place"]
144async unsafe fn surface_async_drop_in_place<T: AsyncDrop + ?Sized>(ptr: *mut T) {
145 // SAFETY: We call this from async drop `async_drop_in_place_raw`
146 // which has the same safety requirements
147 unsafe { <T as AsyncDrop>::async_drop(self:Pin::new_unchecked(&mut *ptr)).await }
148}
149
150/// Basically calls `Drop::drop` with pointer. Used to simplify generation
151/// of the code for `async_drop_in_place_raw`
152#[allow(drop_bounds)]
153#[lang = "async_drop_surface_drop_in_place"]
154async unsafe fn surface_drop_in_place<T: Drop + ?Sized>(ptr: *mut T) {
155 // SAFETY: We call this from async drop `async_drop_in_place_raw`
156 // which has the same safety requirements
157 unsafe { crate::ops::fallback_surface_drop(&mut *ptr) }
158}
159
160/// Wraps a future to continue outputing `Poll::Ready(())` once after
161/// wrapped future completes by returning `Poll::Ready(())` on poll. This
162/// is useful for constructing async destructors to guarantee this
163/// "fuse" property
164struct Fuse<T> {
165 inner: Option<T>,
166}
167
168#[lang = "async_drop_fuse"]
169fn fuse<T>(inner: T) -> Fuse<T> {
170 Fuse { inner: Some(inner) }
171}
172
173impl<T> Future for Fuse<T>
174where
175 T: Future<Output = ()>,
176{
177 type Output = ();
178
179 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
180 // SAFETY: pin projection into `self.inner`
181 unsafe {
182 let this: &mut Fuse = self.get_unchecked_mut();
183 if let Some(inner: &mut T) = &mut this.inner {
184 ready!(Pin::new_unchecked(inner).poll(cx));
185 this.inner = None;
186 }
187 }
188 Poll::Ready(())
189 }
190}
191
192/// Async destructor for arrays and slices.
193#[lang = "async_drop_slice"]
194async unsafe fn slice<T>(s: *mut [T]) {
195 let len: usize = s.len();
196 let ptr: *mut T = s.as_mut_ptr();
197 for i: usize in 0..len {
198 // SAFETY: we iterate over elements of `s` slice
199 unsafe { async_drop_in_place_raw(to_drop:ptr.add(count:i)).await }
200 }
201}
202
203/// Construct a chain of two futures, which awaits them sequentially as
204/// a future.
205#[lang = "async_drop_chain"]
206async fn chain<F, G>(first: F, last: G)
207where
208 F: IntoFuture<Output = ()>,
209 G: IntoFuture<Output = ()>,
210{
211 first.await;
212 last.await;
213}
214
215/// Basically a lazy version of `async_drop_in_place`. Returns a future
216/// that would call `AsyncDrop::async_drop` on a first poll.
217///
218/// # Safety
219///
220/// Same as `async_drop_in_place` except is lazy to avoid creating
221/// multiple mutable refernces.
222#[lang = "async_drop_defer"]
223async unsafe fn defer<T: ?Sized>(to_drop: *mut T) {
224 // SAFETY: same safety requirements as `async_drop_in_place`
225 unsafe { async_drop_in_place(to_drop) }.await
226}
227
228/// If `T`'s discriminant is equal to the stored one then awaits `M`
229/// otherwise awaits the `O`.
230///
231/// # Safety
232///
233/// User should carefully manage returned future, since it would
234/// try creating an immutable referece from `this` and get pointee's
235/// discriminant.
236// FIXME(zetanumbers): Send and Sync impls
237#[lang = "async_drop_either"]
238async unsafe fn either<O: IntoFuture<Output = ()>, M: IntoFuture<Output = ()>, T>(
239 other: O,
240 matched: M,
241 this: *mut T,
242 discr: <T as DiscriminantKind>::Discriminant,
243) {
244 // SAFETY: Guaranteed by the safety section of this funtion's documentation
245 if unsafe { discriminant_value(&*this) } == discr {
246 drop(other);
247 matched.await
248 } else {
249 drop(matched);
250 other.await
251 }
252}
253
254/// Used for noop async destructors. We don't use [`core::future::Ready`]
255/// because it panics after its second poll, which could be potentially
256/// bad if that would happen during the cleanup.
257#[derive(Clone, Copy)]
258struct Noop;
259
260#[lang = "async_drop_noop"]
261fn noop() -> Noop {
262 Noop
263}
264
265impl Future for Noop {
266 type Output = ();
267
268 fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
269 Poll::Ready(())
270 }
271}
272