Skip to content

test: pin read_env's completion-behavior claims for get_scheduler() (#2098) - #2338

Merged
ericniebler merged 3 commits into
NVIDIA:mainfrom
alwaysprince05:test/2098-read-env-completion-behavior
Oct 20, 2026
Merged

ericniebler merged 3 commits into
NVIDIA:mainfrom
alwaysprince05:test/2098-read-env-completion-behavior

Conversation

@alwaysprince05

@alwaysprince05 alwaysprince05 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

A regression guard for the co_await path in #2098.

read_env may advertise inline completion only for the completion tags it can
actually send. It advertised more than that before 9a301946, so a task that
co_awaits

get_scheduler() | let_value([](auto sch) { return schedule(sch); })

was classified as completing inline. The awaiter then kept the composed
operation state in its own stack frame while a nested schedule() operation was
still queued, which is the lifetime bug reported in #2098.

These assertions pin the current behaviour:

  • get_scheduler() claims inline completion for set_value_t — read_env
    completes in its start();
  • it does not claim set_error_t or set_stopped_t, which it never sends;
  • the composition above completes inline for set_value_t — let_value
    forwards read_env's inline value completion — but not for set_stopped_t
    (the nested schedule() completes asynchronously), which is what keeps a
    co_await on it from being treated as completing inline.

All hold on current main and fail at 482c2605, so a regression of the
completion-behaviour claim is caught at compile time rather than as a crash.
Type-level rather than a runtime test, so it needs no sanitizer to be
deterministic.

The composition is asserted with the exported per-tag __completes_inline
concept rather than __as_awaitable::__completes_inline: the latter is not part
of the std.exec module's exported surface (the modular build rejects the name,
and nvc++ cannot resolve the namespace), while the exported concept is used the
same way elsewhere in the test suite. It still discriminates the composition
from the buggy state, since the stopped tag is what moves there.

Since inline completion under co_await requires every tag to complete inline,
the single-tag form of the exported concept is sufficient to pin the
composition; the two read_env claims and the composition's tags are checked
separately so a failure says which one moved.

Built and run with Apple clang 21, -std=c++20, in both configurations:
test.stdexec passes 630 test cases / 50088 assertions with and without
STDEXEC_ENABLE_EXTRA_TYPE_CHECKING against the current base, no new warnings,
clang-format clean.

@copy-pr-bot

copy-pr-bot Bot commented Oct 15, 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.

…VIDIA#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.
@alwaysprince05
alwaysprince05 force-pushed the test/2098-read-env-completion-behavior branch from 9acb47c to ed4cb1d Compare October 15, 2026 16:13
@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test ed4cb1d

@alwaysprince05

Copy link
Copy Markdown
Contributor Author

Updated the branch with main to get a clean CI signal. Should be ready to go once the workflow approval clears.

@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 74c6e71

…heck

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 482c260.
@alwaysprince05

Copy link
Copy Markdown
Contributor Author

All four failures traced to the last assertion, which named
ex::__as_awaitable::__completes_inline. That namespace is not part of the
std.exec module's exported surface: the clang-trunk modules build rejected the
name ("must be declared before it is used"), and nvc++ could not resolve it at
all ("name followed by '::' must be a class or namespace name"). The
non-modular configs pass because there the names are reachable by include.

Pushed 4e6d5b8d, replacing that assertion with per-tag checks on the exported
__completes_inline concept: the composition completes inline for set_value_t
(let_value forwards read_env's inline value completion) but not for
set_stopped_t (the nested schedule() completes asynchronously). Both hold on
current main and fail at 482c2605, so the pinned behaviour is unchanged; only
the spelling is portable across the module and nvc++ configurations.

@ericniebler

Copy link
Copy Markdown
Collaborator

/ok to test 4e6d5b8

@ericniebler
ericniebler merged commit 8398d5a into NVIDIA:main Oct 20, 2026
71 of 72 checks passed
@alwaysprince05
alwaysprince05 deleted the test/2098-read-env-completion-behavior branch October 20, 2026 18: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.

2 participants