Date: Thu, 11 Sep 2025 17:27:38 -0400
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.
<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.
Received on 2025-09-11 21:27:51