Is it okay to destroy a coroutine-handle via a type-erased std::coroutine_handle<>
? I assume it is, because corresponding code seems to compile. If so, how does this work under the hood? How does the compiler/runtime know what the actual type of the promise is (so that it knows which destructors to call)?
Yes it is perfectly ok to do that. std::coroutine_handle<>
is designed to work just fine as a type erased handle. The only use for explicitly specifying the promise type is when you need to access the promise object of the coroutine.
As for how the coroutine handle knows how to destroy the promise... well it doesn't. It's all managed by the coroutine state object (that the coroutine handle points to). The coroutine state is responsible for managing, not only the promise object, but also any local variables of the coroutine body as well as keep track of the current suspension point. The actual details are all implementation defined.
An example of how can a type-erased coroutine handle invoke the appropriate destroy
function for a given coroutine state, is to call it indirectly through a function pointer stored on the coroutine frame, which is the case with clang according to its docs
The ‘llvm.coro.destroy’ intrinsic destroys a suspended switched-resume coroutine.
[..] when possible, the coro.destroy intrinsic is replaced with a direct call to the coroutine destroy function. Otherwise it is replaced with an indirect call based on the function pointer for the destroy function stored in the coroutine frame.