https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100127
--- Comment #4 from Iain Sandoe <iains at gcc dot gnu.org> --- (In reply to Riccardo Brugo from comment #0) > Created attachment 50621 [details] Of course, we should not ICE - but ... > struct promise_type { > std::optional<value_type> _value = std::nullopt; > > future get_return_object() { > return future{handle_type::from_promise(*this)}; > } > void return_value(value_type val) { > _value = static_cast<value_type &&>(val); > } > auto initial_suspend() noexcept { > class awaiter { > std::optional<value_type> & value; > public: > explicit awaiter(std::optional<value_type> & val) noexcept : > value{val} {} > bool await_ready() noexcept { return value.has_value(); } > void await_suspend(handle_type) noexcept { } > value_type & await_resume() noexcept { return *value; } > }; > > return awaiter{_value}; > } The ICE is caused by the code handling a reference from the co_await - where it was not expecting any value to be returned from the initial or final await_resume() functions. --- How do you expect to use the value returned by value_type & await_resume() noexcept { return *value; } in this? see: https://eel.is/c++draft/dcl.fct.def.coroutine#5 essentially the value(s) of the initial and final co_await expressions are discarded. So of course, you can have any side-effect you like from the evaluation of the expressions - but there is no way for you to see the result of the await_resume(). Ergo it might as well be void... however, let's fix the ICE anyway.