From ed4cb1d90ed8c46a18646147c2d713d6d3d250ba Mon Sep 17 00:00:00 2001 From: alwaysprince05 Date: Thu, 15 Oct 2026 21:32:45 +0530 Subject: [PATCH 1/2] test: pin read_env's completion-behavior claims for get_scheduler() (#2098) read_env may advertise inline completion only for the completion tags it can actually send. When it advertised more than that, a task co_awaiting get_scheduler() | let_value(schedule) was classified as completing inline, so the awaiter kept the composed operation state in its own stack frame while a nested schedule() operation was still queued. Assert that get_scheduler() claims inline completion for set_value_t alone, and that the composed expression is not treated as completing inline. --- .../queries/test_get_completion_behavior.cpp | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) 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>); From 4e6d5b8d39d86abf21609c4b6ace6a6e88293ab1 Mon Sep 17 00:00:00 2001 From: alwaysprince05 Date: Sun, 18 Oct 2026 09:01:54 +0530 Subject: [PATCH 2/2] fix(test): use module-exported names in get_scheduler() composition check The final assertion named ex::__as_awaitable::__completes_inline, which is not part of the stdexec module's exported surface: the clang-trunk modules build rejected the name ("must be declared before it is used") and nvc++ could not resolve the namespace at all ("name followed by '::' must be a class or namespace name"), failing 4 CI configurations. Replace it with assertions on the exported per-tag concept: the composition's set_value_t completes inline (let_value forwards read_env's inline value completion), while its set_stopped_t does not (the nested schedule() completes asynchronously), so a co_await on it must not be treated as completing inline. Both hold on current main and fail at 482c2605. --- .../queries/test_get_completion_behavior.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/stdexec/queries/test_get_completion_behavior.cpp b/test/stdexec/queries/test_get_completion_behavior.cpp index 95e37585c..6b4806d72 100644 --- a/test/stdexec/queries/test_get_completion_behavior.cpp +++ b/test/stdexec/queries/test_get_completion_behavior.cpp @@ -84,5 +84,18 @@ inline constexpr auto __reschedule = [](auto __sch) }; inline constexpr auto __reschedule_on_current = ex::get_scheduler() | ex::let_value(__reschedule); -static_assert( - !ex::__as_awaitable::__completes_inline>); +// 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<>>);