Open
Description
Appears, that compiler passes .done() handle into await_suspend, which should never happen.
Returning handle of coroutine from its final_suspend should be correct and may be used to "continue" coroutine and free memory
https://godbolt.org/z/oeh5Tooxb
#include <coroutine>
#include <iostream>
struct transfer_control_to {
std::coroutine_handle<> waiter;
bool await_ready() const noexcept { return false; }
std::coroutine_handle<> await_suspend(std::coroutine_handle<> h) noexcept {
if (h.done()) {
std::cout << "IMPOSSIBLE HAPPEN" << std::endl;
h.destroy();
return std::noop_coroutine();
}
return waiter;
}
static void await_resume() noexcept {}
};
struct task_promise {
std::coroutine_handle<void> waiter;
static constexpr std::suspend_always initial_suspend() noexcept { return {}; }
static void return_void() {}
auto get_return_object() {
return std::coroutine_handle<task_promise>::from_promise(*this);
}
void unhandled_exception() noexcept {}
auto final_suspend() noexcept { return transfer_control_to{waiter}; }
};
struct task {
using promise_type = task_promise;
using handle_type = std::coroutine_handle<promise_type>;
handle_type handle_;
constexpr task(handle_type handle) noexcept : handle_(handle) {}
void start_and_detach() {
handle_.promise().waiter = handle_;
handle_.resume();
handle_ = nullptr;
}
};
task foo() { co_return; }
void bar() {
auto t = foo();
t.start_and_detach();
}
int main() { bar(); }