Starting a stdexec::task with starts_on on a stdexec::task_scheduler produces a sender
that I cannot sync_wait, and cannot co_await from another task. The same code with the
concrete scheduler compiles.
#include <stdexec/execution.hpp>
namespace ex = stdexec;
auto child() -> ex::task<void> { co_return; }
int main() {
ex::run_loop loop;
ex::sync_wait(
ex::starts_on(ex::task_scheduler{loop.get_scheduler()}, child()));
}
g++ -std=c++26 -Iinclude -fsyntax-only repro.cpp
fails with:
include/stdexec/__detail/__domain.hpp:297:21: error: static assertion failed: the sender claims to complete on a domain that is not the domain of its completion scheduler
297 | static_assert(__same_as<_Domain, __detail::__scheduler_domain_t<_Sch, _Env const &...>>,
clang 21.1.8 reports the same static_assert at the same line.
The same failure appears when the sender is awaited from another task:
auto parent() -> ex::task<void> {
auto sched = co_await ex::get_start_scheduler();
co_await ex::starts_on(sched, child());
}
int main() {
ex::run_loop loop;
ex::sync_wait(ex::starts_on(loop.get_scheduler(), parent()));
}
Here sched deduces to stdexec::task_scheduler, even though parent() itself is
started on the concrete run_loop::scheduler.
Variants, all with the same child():
| variant |
result |
sync_wait(starts_on(task_scheduler{s}, child())) |
fails |
co_await starts_on(task_scheduler{s}, child()) inside a task |
fails |
sync_wait(starts_on(s, child())) with the concrete scheduler s |
compiles |
sync_wait(starts_on(task_scheduler{s}, just())) |
compiles |
sync_wait(starts_on(task_scheduler{s}, just() | let_value(child))) |
compiles |
sync_wait(child() | write_env(prop{get_start_scheduler, task_scheduler{s}})) |
compiles |
connect(starts_on(task_scheduler{s}, child()), some_receiver{}) |
compiles |
spawn(starts_on(task_scheduler{s}, child()) | upon_error(...), scope.get_token()) |
compiles |
completion_signatures_of_t<decltype(starts_on(task_scheduler{s}, child())), env<>> |
compiles |
Is starts_on with a task_scheduler and a task child expected to be usable with
sync_wait / co_await, or is the type-erased scheduler meant to be used differently here?
Tested at f91f6363 with g++ 15.2.0 and clang 21.1.8, both -std=c++26.
Starting a
stdexec::taskwithstarts_onon astdexec::task_schedulerproduces a senderthat I cannot
sync_wait, and cannotco_awaitfrom another task. The same code with theconcrete scheduler compiles.
fails with:
clang 21.1.8 reports the same static_assert at the same line.
The same failure appears when the sender is awaited from another task:
Here
scheddeduces tostdexec::task_scheduler, even thoughparent()itself isstarted on the concrete
run_loop::scheduler.Variants, all with the same
child():sync_wait(starts_on(task_scheduler{s}, child()))co_await starts_on(task_scheduler{s}, child())inside a tasksync_wait(starts_on(s, child()))with the concrete schedulerssync_wait(starts_on(task_scheduler{s}, just()))sync_wait(starts_on(task_scheduler{s}, just() | let_value(child)))sync_wait(child() | write_env(prop{get_start_scheduler, task_scheduler{s}}))connect(starts_on(task_scheduler{s}, child()), some_receiver{})spawn(starts_on(task_scheduler{s}, child()) | upon_error(...), scope.get_token())completion_signatures_of_t<decltype(starts_on(task_scheduler{s}, child())), env<>>Is
starts_onwith atask_schedulerand a task child expected to be usable withsync_wait/co_await, or is the type-erased scheduler meant to be used differently here?Tested at
f91f6363with g++ 15.2.0 and clang 21.1.8, both-std=c++26.