Open ccotter opened 1 year ago
You would agree that there is an important difference between a function that returns and int
and one that returns and int&
, right? The same issue applies here. A receiver is going to see int&
. Is the identity of the parameter important or is it not? What if the sender has both set_value_t(int)
and set_value_t(int&)
in its list of completion signatures?
This warning is very much intentional. It's to catch problems that can creep in because of these subtle type mismatches that would be very hard to track down otherwise.
Make sense?
EDIT: P.S., You can simply cast the lvalue to a prvalue with set_value(move(rcvr), int(v))
.
P.P.S., I am thrilled that this feature is working and helping people find these bugs in their code.
Yes, this makes sense.
P.P.S., I am thrilled that this feature is working and helping people find these bugs in their code.
Yes, I didn't realized stdexec had it! I wrote an incompletely and hacky runtime based (not compile time) version a while back for unifex to help track down similar issues (https://github.com/facebookexperimental/libunifex/pull/545 in particular). Things get interesting in the implementation of algos like let_value
which have internal receivers whose set_value
take forwarding reference parameters, and care must be taken to send the right values to the original receiver.
I arrived at my example code above while trying to trace through a compiler error with co_await UnifexcSender{}
(UnifexSender
is a unifex vocabulary sender), which triggered one of the very hard to track down compiler errors that you alluded to. unifex's finally
has been a good proxy for catching type mismatches in completions since internally, unifex::finally
asserts on the actual type sent against what it expects (via unifex::manual_lifetime_union
's assert).
Two related questions on my plate are why sync_wait(StdexecSender{})
does not trigger the diagnostic, and why co_await StdexecSender{}
does not either (not sure if related to any type erasure happening).
Is there language in P2300 stating that sending unexpected values is undefined (or other) behavior? I looked a while ago but wasn't able to find it. Not sure if this would be expected to appear in the paper or not.
Ah ok, sync_wait(StdexecSender{})
does not trigger the warning since nothing in that instantiation instantiates completion_signatures_of_t
which contains the logic to check the types. exec::finally
does instantiate completion_signatures_of_t
. Should we add using __checked_signatures [[maybe_unused]] = completion_signatures_of_t(...)
into sync_wait
and possibly other places?
That sounds like a good idea
In the sample code below, compiling with gcc-13 (
g++-13 -std=c++20 set_value.cpp -I stdexec/include -c
), my bespoke sender claims it completes withset_value_t(int)
, although the implementation ends up sending an lvaluev
, anint
declared on the stack.I get the following diagnostic.
The key part is
This makes sense given that technically, I should be sending
std::move(v)
or something of that nature. That said, the lvaluev
is convertible to a plain value (I'm not sure what the type category is called here). My understanding is thatset_value
is akin to returning from a function. A function declared returningint
can writereturn v
- should I be able to writeset_value(v)
here?