Skip to content

Commit 1a5cdbb

Browse files
committed
Update docs.
1 parent 2038771 commit 1a5cdbb

1 file changed

Lines changed: 36 additions & 20 deletions

File tree

compiler/rustc_mir_transform/src/elaborate_drop.rs

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)