C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relaxing coroutine return_value/return_void restrictions

From: Avi Kivity <avi_at_[hidden]>
Date: Fri, 12 Sep 2025 19:13:55 +0300
On Fri, 2025-09-12 at 11:48 -0400, Jason McKesson via Std-Proposals
wrote:
> On Fri, Sep 12, 2025 at 11:40 AM Avi Kivity <avi_at_[hidden]> wrote:
> >
> > On Thu, 2025-09-11 at 17:27 -0400, Jason McKesson via Std-Proposals
> > wrote:
> >
> > On Thu, Sep 11, 2025 at 7:21 AM Avi Kivity via Std-Proposals
> > <std-proposals_at_[hidden]> wrote:
> >
> >
> > The Standard says
> >
> > If searches for the names return_void and return_value in the scope
> >
> > of the promise type each find any declarations, the program is ill-
> > formed.
> >
> > However, there are cases where one wants both "co_return;" and
> > co_return something;" statements in the same coroutine.
> >
> > The cases are when the coroutine returns a sum type such as
> > std::future
> > or std::expected, and one of the options is void (e.g.
> > std::future<void> or std::expected<void, something>. In these
> > cases,
> > one would want
> >
> >
> > co_return;
> >
> > to select the void branch of the sum type
> >
> > and
> >
> > co_return std::make_exception_ptr(...) // for std::future<void>
> >
> > or
> >
> > co_return something(...) // for std::expected<void, something>.
> >
> >
> > to select the non-void branch.
> >
> > Early versions of gcc did not error when both return_value() and
> > return_void() were defined; no problems were observed.
> >
> >
> > From a conceptual perspective, `return` and `co_return` should
> > behave
> > similarly. As it currently stands, any function for which `return
> > <expr>;` is valid is one where `return;` would not be valid. So it
> > conceptually makes sense that `co_return` would behave the same
> > way.
> >
> > That having been said, there's a reasonable argument to be made
> > that
> > the behavior of `co_return` is already fairly divergent from
> > `return`.
> > Of particular note is the fact that the relationship between the
> > returned expression type (if any) and the function's apparent
> > return
> > type is not nearly as clear as it is for `return`. You may have to
> > dig
> > deeply into the coroutine machinery to figure out exactly what type
> > you need to provide, if any.
> >
> > Also, there's the fact that coroutines can already have *multiple*
> > different "return types": the type you can put into `co_return`. So
> > you can already do `co_return X;` and `co_return Y;` where those
> > two
> > types have no conversion relationship between them or with some
> > other
> > third type. Adding `co_return;` to that list seems pretty
> > reasonable,
> > even if it does call a differently named function internally.
> >
> >
> >
> >
> > Even for plain `return`, sum types make the case for both return;
> > and return expr; in the same function.
> >
> > A function f that returns std::expected<T, E> can "return T();" or
> > it can "return std::unexpected(E());".
>
> That's made possible via implicit conversions with a known return
> type. Try that in a deduced return function and it will fail.


But I'm trying it in a function that explicitly return std::expected<T,
E>.


>
> > A function g that returns std::unexpected<void, E> cannot do the
> > analogous and "return;" for the good case and "return
> > std::unexpected(E());" for the bad case.
>
> And it shouldn't. `return;` should mean "exit without returning a
> value".



That's exactly what a return type of std::expected<void, E> conveys.
Either we return with no value, or we return with an unexpected value.

We have to emulate no value with {} or with std::expected<void, E>().
Given low usage of std::expected so far and the low cost of returning
{}, that's bearable. To be clear I'm not advocating a change to
"return" and if someone points to this thread I will claim a cat walked
over my keyboard.

However, future<void> is very common in async code, and the ability to
either co_return; or co_return an exception_ptr is very desirable, and
low cost to implement.

Received on 2025-09-12 16:14:00