Skip to content

Allow just to Throw on Connect#1578

Merged
ericniebler merged 2 commits intoNVIDIA:mainfrom
RobertLeahy:just
Jul 20, 2025
Merged

Allow just to Throw on Connect#1578
ericniebler merged 2 commits intoNVIDIA:mainfrom
RobertLeahy:just

Conversation

@RobertLeahy
Copy link
Copy Markdown
Contributor

Previously if connecting a just sender with a receiver threw due to a throwing move operation terminate was called due to an exception passing through noexcept.

Sending completion signals to receivers must not throw, including
set_value. This is enforced as can be seen in this error which was
observed before the application of this commit:

  /stdexec/__detail/__receivers.hpp:47:11: error: static assertion failed: set_value member functions must be noexcept
     47 |           noexcept(static_cast<_Receiver&&>(__rcvr).set_value(static_cast<_As&&>(__as)...)),
        |           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

An obvious consequence of the above is that the set_value member
function(s) of a receiver must be marked noexcept. However the
evaluation of a function itself is not the only thing that can throw
when invoking a function: The population of the parameters thereto may
emit an exception. For example a function may accept parameters by value
thereby requiring the caller to copy or move the arguments thereto.

Since, as alluded to above, the parameters are populated in the context
of the caller the only thing a function can do to prevent such
exceptions is to accept its parameters by reference (thereby obviating
the need to move construct arguments thereto). Previously the test
helper fun_receiver did not do this leading to the error provided above.

Updated fun_receiver::set_value to accept parameters by forwarding
reference thereby allowing it to accept parameters whose move
constructors are not noexcept.
A just sender that isn't nullary contains one or more objects. These
objects are transmitted thereinto by the sender factory therefor. Since
copying and moving objects can throw the just sender factory can also
throw (this is demonstrated by the unit test added by this commit).

In order to be useful a sender must be connected with a receiver to form
an operation state. Since the just operation does not yield the objects
passed to the sender factory therefor until the operation has been
started it is clear those objects must in turn be transmitted from the
sender to the operation state at connect time. If initially providing
those objects can throw then so too can propagating them from the sender
to the operation state. That is to say that not only can the just sender
factory throw but so too can connecting a just sender with a receiver.

Before this commit if a just sender was connected, and one of the move
operations involved therein threw an exception, the program would
terminate due to the fact the exception would attempt to pass through a
constructor marked noexcept. The code involved (changed by this commit)
attempted to accurately reflect the noexcept-ness of the operations
involved by checking:

  __noexcept_of<__sexpr_impl<__tag_t>::get_state, _Sexpr, _Receiver&>

However this merely checks if the evaluation of some function throws an
exception. In the case wherein a just sender is being connected the
evaluation does not throw and therefore the above expression correctly
yields true. The function is not merely invoked however, the value
returned thereby is used to populate a data member in the constructor
initializer list. In the instance of just the invocation yields an
rvalue reference and therefore a move operation must occur, one which
may throw an exception. To account for this the noexcept check must be:

  noexcept(__state_t(__sexpr_impl<__tag_t>::get_state(static_cast<_Sexpr&&>(__sndr), __rcvr_)))

Which is what it is changed to by this commit.
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented Jul 20, 2025

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.

Comment thread include/stdexec/__detail/__basic_sender.hpp
@ericniebler
Copy link
Copy Markdown
Collaborator

/ok to test daf9a01

@ericniebler ericniebler merged commit de92b54 into NVIDIA:main Jul 20, 2025
18 checks passed
@ericniebler
Copy link
Copy Markdown
Collaborator

Thanks Robert!

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