@@ -199,13 +199,30 @@ where
199199 self . elaborator . tcx ( )
200200 }
201201
202- /// Generates three blocks:
203- /// * #1:pin_obj_bb: call Pin<ObjTy>::new_unchecked(&mut obj)
204- /// * #2:call_drop_bb: fut = call obj.<AsyncDrop::drop>() OR call async_drop_in_place<T>(obj)
205- /// * #3:drop_term_bb: drop (obj, fut, ...)
206- /// We keep async drop unexpanded to poll-loop here, to expand it later, at StateTransform -
207- /// into states expand.
208- /// call_destructor_only - to call only AsyncDrop::drop, not full async_drop_in_place glue
202+ /// Async-drop `place: drop_ty`.
203+ ///
204+ /// Conceptually, we want to run `async_drop_in_place(&mut obj).await`.
205+ ///
206+ /// Await syntax does not exist in MIR, so we need to manually expand it into a poll-yield
207+ /// loop, essentially:
208+ /// ```mir
209+ /// let fut = async_drop_in_place(&mut obj);
210+ /// loop {
211+ /// let pin_fut = Pin::new_unchecked(&mut fut);
212+ /// match Future::poll(pin_fut, CTX_ARG) {
213+ /// Poll::Ready => break,
214+ /// Poll:Pending(..) => CTX_ARG = yield (),
215+ /// }
216+ /// }
217+ /// // continue to `succ`
218+ /// ```
219+ ///
220+ /// We also need to ensure that async drop also happens on the coroutine drop path, ie. when
221+ /// `yield` branches along its `drop` target. This requires a second loop, this time jumping to
222+ /// `dropline`.
223+ ///
224+ /// Arguments:
225+ /// `call_destructor_only`: call only `AsyncDrop::drop`, not full `async_drop_in_place` glue
209226 #[ instrument( level = "debug" , skip( self ) , ret) ]
210227 fn build_async_drop (
211228 & mut self ,
@@ -336,8 +353,8 @@ where
336353 } ;
337354
338355 // #2:call_drop_bb >>>
339- // ` call AsyncDrop::drop(pin_obj)`
340- // OR ` call async_drop_in_place(pin_obj.pointer)`
356+ // call AsyncDrop::drop(pin_obj)
357+ // OR call async_drop_in_place(pin_obj.pointer)
341358 let pin_adt_def = tcx. adt_def ( tcx. require_lang_item ( LangItem :: Pin , span) ) ;
342359 let pin_obj_ty = Ty :: new_adt ( tcx, pin_adt_def, tcx. mk_args ( & [ obj_ref_ty. into ( ) ] ) ) ;
343360 // Where we store the result of Pin<&drop_ty>::new_unchecked(&mut place).
@@ -424,18 +441,17 @@ where
424441 /// the future returns `Poll::Pending` and continuing to `ready_target`
425442 /// when it returns `Poll::Ready`.
426443 ///
427- /// The generated sequence:
428- /// - stores the `resume_arg_source` into a temporary context value;
429- /// - constructs a pinned reference to `fut_place` using `Pin::new_unchecked`;
430- /// - calls the future's `poll` function with the pinned future and the context reference;
431- /// - switches on the `Poll` discriminant: on `Ready` jump to
432- /// `ready_target`, on `Pending` emit a `Yield` with `yield_value` that
433- /// resumes back into the poll loop.
444+ /// Pseudo-code:
445+ /// ```mir
446+ /// pin_bb:
447+ /// let pin_fut = Pin::new_unchecked(&mut fut_place);
448+ /// match Future::poll(pin_fut, CTX_ARG) {
449+ /// Poll::Ready => goto succ,
450+ /// Poll::Pending(..) => CTX_ARG = yield () [resume: resume_bb, drop: drop_bb],
451+ /// }
452+ /// ```
434453 ///
435- /// Returns:
436- /// - the entry block (the pin-future block),
437- /// - the yield resume block,
438- /// - the drop resume block.
454+ /// Returns: the tuple `(pin_bb, resume_bb, drop_bb)`.
439455 #[ instrument( level = "trace" , skip( self ) , ret) ]
440456 fn build_pin_poll_yield_loop (
441457 & mut self ,
0 commit comments