This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.

4133. awaitable-receiver's members are potentially throwing

Section: 33.13.1 [exec.as.awaitable] Status: WP Submitter: Eric Niebler Opened: 2024-07-30 Last modified: 2026-03-31

Priority: 1

View other active issues in [exec.as.awaitable].

View all other issues in [exec.as.awaitable].

View all issues with WP status.

Discussion:

The specification of awaitable-receiver in 33.13.1 [exec.as.awaitable]/p4 as of N4988 is not taking into consideration the fact that the resume() and promise() member functions on coroutine_handle<P> are not marked noexcept. awaitable-receiver's member functions must all be noexcept, but they are specified as being "equivalent to" statement that call resume() and promise() outside of try/catch blocks.

[2024-08-21; Reflector poll]

Set priority to 1 after reflector poll.

promise() can probably be Throws: Nothing (along with a bunch of other coroutine_handle members), but resume() certainly can throw. Also AS-EXCEPT-PTR can throw for the error_code case (that might be worth a separate issue though).

[2026-03-27; Tim adds wording following LWG discussion]

[Croydon 2026-03-27; Status changed: New → Immediate.]

[Croydon 2026-03-28; Status changed: Immediate → WP.]

Proposed resolution:

This wording is relative to N5032.

  1. Modify 33.13.1 [exec.as.awaitable] as indicated:

    -4- Let rcvr be an rvalue expression of type awaitable-receiver, let crcvr be a const lvalue that refers to rcvr, let vs be a pack of subexpressions, and let err be an expression of type Err. Let MAKE-NOEXCEPT(expr) for some subexpression expr be expression-equivalent to [&] noexcept -> decltype(auto) { return (expr); }(). Then:

    1. (4.1) — If constructible_from<result-type, decltype((vs))...> is satisfied, the expression set_value(rcvr, vs...) is equivalent to:

      try {
        rcvr.result-ptr->template emplace<1>(vs...);
      } catch(...) {
        rcvr.result-ptr->template emplace<2>(current_exception());
      }
      MAKE-NOEXCEPT(rcvr.continuation.resume());
      

      Otherwise, set_value(rcvr, vs...) is ill-formed.

    2. (4.2) — The expression set_error(rcvr, err) is equivalent to:

      try {
        rcvr.result-ptr->template emplace<2>(AS-EXCEPT-PTR(err));
      } catch(...) {
        rcvr.result-ptr->template emplace<2>(current_exception());
      }
      MAKE-NOEXCEPT(rcvr.continuation.resume());
      
    3. (4.3) — The expression set_stopped(rcvr) is equivalent to:

      MAKE-NOEXCEPT(static_cast<coroutine_handle<>>(rcvr.continuation.promise().unhandled_stopped()).resume());
      
    4. (4.4) — For any expression tag whose type satisfies forwarding-query and for any pack of subexpressions as, get_env(crcvr).query(tag, as...) is expression-equivalent to:

      tag(get_env(as_const(MAKE-NOEXCEPT(crcvr.continuation.promise()))), as...)