Skip to content

fix: require schedule() to return a stdexec sender in the scheduler concept - #2259

Merged
ericniebler merged 1 commit into
NVIDIA:mainfrom
alwaysprince05:test/scheduler-concept-check-1406
Sep 16, 2026
Merged

ericniebler merged 1 commit into
NVIDIA:mainfrom
alwaysprince05:test/scheduler-concept-check-1406

Conversation

@alwaysprince05

Copy link
Copy Markdown
Contributor

Fixes #1406.

The problem, as it stands today

The original report (2024) was that stdexec::scheduler<S> hard-errored for foreign scheduler types. On current main that specific failure mode is gone, but investigating it with a repro exposed the remaining defect — the inverse one:

stdexec::scheduler<foreign_scheduler> currently evaluates to true for a type whose schedule() returns something that is not a stdexec sender (no sender_concept alias, not enabled via enable_sender). __callable<schedule_t, S> succeeds, and the sender check only fires as a hard static_assert inside the schedule CPO body — at the point of actual use, not at the concept. So the concept answers the wrong question at the wrong time: a false positive up front, and a hard error later.

The fix

Add a SFINAE-safe clause to the concept in include/stdexec/__detail/__schedulers.hpp:

template <class _Scheduler>
concept __returns_stdexec_sender = requires(_Scheduler &&__sched) {
  { schedule(static_cast<_Scheduler &&>(__sched)) } -> sender;
};

template <class _Scheduler>
concept scheduler = __callable<schedule_t, _Scheduler>  //
                 && __returns_stdexec_sender<_Scheduler>
                 && ...;

What's here

  • include/stdexec/__detail/__schedulers.hpp: the new __returns_stdexec_sender concept, wired into scheduler, plus doc-comment updates.
  • test/stdexec/concepts/test_concept_scheduler.cpp (3 new cases, existing file/style):
    • foreign scheduler returning a non-stdexec sender does not model scheduler (value, lvalue-ref, and const-lvalue-ref forms)
    • schedule() returning void does not model scheduler
    • a foreign type with no scheduler_concept alias whose schedule() returns a real stdexec sender does model scheduler (behavioral opt-in)

Verification

  • test.stdexec: 3534 assertions / 622 cases pass (Release, Apple Clang 21)
  • test.exec: 3417 assertions / 362 cases pass
  • clang-format 21 clean on both touched files

Happy to restructure if there's a preferred shape for this — e.g. folding the check into __callable<schedule_t, ...> instead of a separate concept.

…oncept

Evaluating stdexec::scheduler<S> for a foreign scheduler type whose
schedule() member returns a non-stdexec sender was a false positive:
__callable<schedule_t, S> succeeded, and the sender check only fired as
a hard error inside the schedule CPO body at the point of use. Add a
SFINAE-safe __returns_stdexec_sender clause to the concept so such types
evaluate to false gracefully, while foreign frameworks whose schedule()
returns a genuine stdexec sender model the concept behaviorally, with no
scheduler_concept alias required. See NVIDIA#1406.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@copy-pr-bot

copy-pr-bot Bot commented Sep 16, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@alwaysprince05

Copy link
Copy Markdown
Contributor Author

Hi @ericniebler — this grew out of the scheduler_concept work in #2256/#2257, so it felt like a natural next step to take on #1406.

I played with a small repro and it turns out the concept now fails in the opposite direction from what was originally reported: a scheduler whose schedule() returns a non-stdexec sender still satisfies stdexec::scheduler, and the failure only shows up later as a hard error inside the CPO. This PR moves that check into the concept itself, so foreign types just evaluate to false — and a foreign framework that returns real stdexec senders models it behaviorally, no alias required, which I believe lines up with what you had in mind in the issue thread.

It's a small change — one extra clause in the concept plus three test cases. test.stdexec and test.exec both pass locally, and clang-format is clean. Could you /ok to test when you get a chance? Thanks!

@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 4f2a398

@ericniebler
ericniebler merged commit abcdee3 into NVIDIA:main Sep 16, 2026
38 of 39 checks passed
@alwaysprince05
alwaysprince05 deleted the test/scheduler-concept-check-1406 branch September 16, 2026 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No way to check whether a scheduler is a stdexec scheduler

2 participants