diff --git a/test/stdexec/queries/test_get_completion_behavior.cpp b/test/stdexec/queries/test_get_completion_behavior.cpp index 37ef0adb8..6b4806d72 100644 --- a/test/stdexec/queries/test_get_completion_behavior.cpp +++ b/test/stdexec/queries/test_get_completion_behavior.cpp @@ -61,3 +61,41 @@ static_assert(cb::__may_be_asynchronous(cb::__asynchronous_affine)); static_assert(cb::__may_be_asynchronous(cb::__asynchronous | cb::__inline_completion)); static_assert(cb::__may_be_asynchronous(cb::__asynchronous_affine | cb::__asynchronous)); static_assert(cb::__may_be_asynchronous(cb::__asynchronous_affine | cb::__inline_completion)); + +// read_env completes in its start(), so get_scheduler() may claim inline completion +// for set_value_t -- but only for the tags it can actually send. Advertising +// inline completion for a tag it never sends made a task that co_awaits +// get_scheduler() | let_value(schedule) look like it completed inline, and the +// awaiter then kept the composed operation state in its own stack frame while a +// nested schedule() operation was still queued (see #2098). +using __get_scheduler_sndr_t = decltype(ex::get_scheduler()); +using __get_scheduler_attrs_t = ex::env_of_t<__get_scheduler_sndr_t>; + +static_assert(ex::__completes_inline); +static_assert(!ex::__completes_inline); +static_assert(!ex::__completes_inline); + +// The same expression from #2098, composed: the successor sender schedule(sch) may +// complete asynchronously, so the composition must not be treated as completing +// inline. +inline constexpr auto __reschedule = [](auto __sch) +{ + return ex::schedule(__sch); +}; +inline constexpr auto __reschedule_on_current = ex::get_scheduler() | ex::let_value(__reschedule); + +// For co_await, a sender is treated as completing inline only if _all_ of its +// completion tags complete inline (see __as_awaitable::__completes_inline). The +// nested schedule(sch) does not complete inline for set_stopped_t, so the +// composition must not be classified as completing inline. We check the stopped +// tag directly; the value tag of the composition _does_ complete inline +// (let_value forwards read_env's inline value completion), so that is pinned +// here as well. This check uses only names exported by the stdexec module: the +// __as_awaitable namespace is not part of the module's public surface, and +// naming it fails the modular and nvc++ configurations. +static_assert(ex::__completes_inline, + ex::env<>>); +static_assert(!ex::__completes_inline, + ex::env<>>);