Skip to content

Check domain transformations in function's noexcept constructor check - #2379

Open
ispeters wants to merge 2 commits into
NVIDIA:mainfrom
ispeters:check-noexcept-through-domain-transform
Open

ispeters wants to merge 2 commits into
NVIDIA:mainfrom
ispeters:check-noexcept-through-domain-transform

Conversation

@ispeters

Copy link
Copy Markdown
Contributor

A noexcept function type promises that invoking its factory and connecting the sender the factory returns don't throw, and its constructors check that promise against the factory. Until now, the check skipped any sender that a domain transforms, trusting both the transformation and the transformed sender's connect, so it accepted factories whose senders can throw when connected, including any sender passed to bulk, whose default lowering isn't declared noexcept.

connect passes the sender through transform_sender first, and its noexcept accounts for the transformation, so this diff checks connect's noexcept for every sender. Checking the transformation when the function is constructed is sound because no caller can change it: the domains that can transform the sender depend only on the sender and on the queries the function type declares.

The new tests check that a noexcept transformation into a sender that connects without throwing is accepted, and that a transformation that may throw, or one into a sender whose connect may throw, is rejected.

@copy-pr-bot

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

@ispeters
ispeters force-pushed the check-noexcept-through-domain-transform branch from 9502c06 to f90b85b Compare October 28, 2026 18:29
@ispeters

Copy link
Copy Markdown
Contributor Author

This depends on #2377.

ispeters and others added 2 commits October 28, 2026 19:32
`transform_sender` transforms a sender repeatedly, until a domain's
transformation returns a sender of the same type, and its `noexcept` is
meant to be the conjunction of the steps'. The step that ends the
recursion reports only its own `noexcept`, though, dropping the earlier
steps'. So when a potentially-throwing transformation returns a
sender that's then transformed again, for example by `default_domain`'s
identity transformation, `transform_sender`, and with it `connect`,
claim not to throw, and an exception thrown by the transformation calls
`std::terminate`.

This diff makes the last step report the conjunction too.

That exposes a missing `noexcept` on `sequence`'s lowering, whose
`transform_sender` had no exception specification, so connecting a
`sequence`, or a `repeat_n`, which connects one, became
potentially-throwing. It's now `noexcept` exactly when moving or copying
the children into the lowered sender is.

The new tests check that a potentially-throwing transformation whose
result is transformed again makes `transform_sender` and `connect`
potentially-throwing, that its exception propagates out of `connect`,
and when lowering a `sequence` is `noexcept`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A `noexcept` function type promises that invoking its factory and
connecting the sender the factory returns don't throw, and its
constructors check that promise against the factory. Until now, the
check skipped any sender that a domain transforms, trusting both the
transformation and the transformed sender's `connect`, so it accepted
factories whose senders can throw when connected, including any sender
passed to `bulk`, whose default lowering isn't declared `noexcept`.

`connect` passes the sender through `transform_sender` first, and its
`noexcept` accounts for the transformation, so this diff checks
`connect`'s `noexcept` for every sender. Checking the transformation
when the function is constructed is sound because no caller can change
it: the domains that can transform the sender depend only on the sender
and on the queries the function type declares.

The new tests check that a `noexcept` transformation into a sender that
connects without throwing is accepted, and that a transformation that
may throw, or one into a sender whose `connect` may throw, is rejected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ispeters
ispeters force-pushed the check-noexcept-through-domain-transform branch from f90b85b to 79a8a26 Compare October 29, 2026 02:32

This branch has not been deployed

No deployments
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.

1 participant