diff --git a/test/stdexec/queries/test_get_completion_behavior.cpp b/test/stdexec/queries/test_get_completion_behavior.cpp index 37ef0adb8..95e37585c 100644 --- a/test/stdexec/queries/test_get_completion_behavior.cpp +++ b/test/stdexec/queries/test_get_completion_behavior.cpp @@ -61,3 +61,28 @@ 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); + +static_assert( + !ex::__as_awaitable::__completes_inline>);