22<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
33
44<issue num =" 4203" status =" New" >
5- <title >constraints on `schedule_from`'s <i >`get-state`</i > function are incorrect</title >
5+ <title >Constraints on <i >`get-state`</i > functions are incorrect</title >
66<section ><sref ref =" [exec.schedule.from]" /></section >
77<submitter >Eric Niebler</submitter >
88<date >03 Feb 2025</date >
99<priority >99</priority >
1010
1111<discussion >
1212<p >
13- Imported from <a href =" https://github.com/cplusplus/sender-receiver/issues/313" >cplusplus/sender-receiver #313</a >.
13+ Imported from:
14+ <a href =" https://github.com/cplusplus/sender-receiver/issues/313" >cplusplus/sender-receiver #313</a >
15+ and
16+ <a href =" https://github.com/cplusplus/sender-receiver/issues/314" >cplusplus/sender-receiver #314</a >.
1417</p >
1518<p >
1619<sref ref =" [exec.schedule.from]" /> p6 reads:
1720
1821<blockquote >
1922The member <code ><i >impls-for</i >< schedule_from_t> ::get-state</code >
2023is initialized with a callable object equivalent to the following lambda:
21- <pre ><code >
22- []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept(<i >see below</i >)
24+ <pre ><code > []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept(<i >see below</i >)
2325 requires sender_in< <i >child-type</i >< Sndr> , env_of_t< Rcvr>> {
2426</code ></pre >
2527</blockquote >
@@ -28,7 +30,74 @@ The constraint should account for the fact that the child sender will
2830be connected with <code ><i >FWD-ENV</i >(get_env(rcvr))</code >.
2931</p >
3032
31- <note >The resolution touches the same text as LWG <iref ref =" 4198" />.</note >
33+ <note >
34+ The resolution touches some of the same text as LWG <iref ref =" 4198" />,
35+ but without conflicting.
36+ </note >
37+
38+ <p >
39+ Imported from:
40+ <a href =" https://github.com/cplusplus/sender-receiver/issues/315" >cplusplus/sender-receiver #315</a >.
41+ </p >
42+ <p >
43+ <sref ref =" [exec.when.all]" /> p6 reads:
44+
45+ <blockquote >
46+ The member <code >impls-for< when_all_t> ::<i >get-env</i ></code >
47+ is initialized with a callable object equivalent to the following lambda
48+ expression:
49+ <pre ><code > []< class State, class Rcvr> (auto&& , State& state, const Receiver& rcvr) noexcept {
50+ return <i >see below</i >;
51+ }
52+ </code ></pre >
53+ Returns an object `e` such that
54+ <ol style =" list-style-type:none" >
55+ <li >(6.1) — `decltype(e)` models <i >`queryable`</i >, and</li >
56+ <li >(6.2) — `e.query(get_stop_token)` is expression-equivalent to
57+ <code >state.<i >stop-src</i >.get_token()</code >, and</li >
58+ <li >(6.3) —
59+ given a query object `q` with type other than <i >cv</i > `stop_token_t`,
60+ `e.query(q)` is expression-equivalent to `get_env(rcvr).query(q)`.
61+ </li >
62+ </ol >
63+ </blockquote >
64+
65+ The problem is in (6.3). It should be forwarding on <i >`forwarding-query`</i >'s
66+ to `get_env(rcvr)` but is is instead forwarding all queries.
67+ </p >
68+
69+ <p >
70+ Imported from:
71+ <a href =" https://github.com/cplusplus/sender-receiver/issues/316" >cplusplus/sender-receiver #316</a >.
72+ </p >
73+ <p >
74+ The child senders should only see the parent's queries if they are forwarding queries.
75+ </p >
76+
77+ <p >
78+ Imported from:
79+ <a href =" https://github.com/cplusplus/sender-receiver/issues/311" >cplusplus/sender-receiver #311</a >.
80+ </p >
81+
82+ <p >
83+ <sref ref =" [exec.stopped.opt]" />/para 3 reads:
84+
85+ <blockquote >
86+ Let `sndr` and `env` be subexpressions such that `Sndr` is `decltype((sndr))`
87+ and `Env` is `decltype((env))`.
88+ If <code ><i >sender-for</i >< Sndr, stopped_as_optional_t> </code > is `false`,
89+ or if the type <code ><i >single-sender-value-type</i >< Sndr, Env> </code >
90+ is ill-formed or `void`,
91+ then the expression `stopped_as_optional.transform_sender(sndr, env)`
92+ is ill-formed; otherwise, it is equivalent to:
93+ </blockquote >
94+ the test for <code >single-sender-value-type< Sndr, Env> </code > is incorrect.
95+ It should be testing its child for single-sender-ness.
96+ </p >
97+ <p >
98+ In addition, it should be applying <i >`FWD-ENV-T`</i > to `Env`
99+ so that only forwarding queries are forwarded.
100+ </p >
32101
33102</discussion >
34103
@@ -65,8 +134,7 @@ Change <sref ref="[exec.schedule.from]"/> as indicated:
65134The member
66135<code ><i >impls-for</i >< schedule_from_t> ::<i >get-state</i ></code >
67136is initialized with a callable object equivalent to the following lambda:
68- <pre ><code >
69- []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept(<i >see below</i >)
137+ <pre ><code > []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept(<i >see below</i >)
70138 requires sender_in< child-type< Sndr> , <ins ><i >FWD-ENV-T</i >(</ins >env_of_t< Rcvr> <ins >)</ins >> {
71139</code ></pre >
72140<p >… </p >
@@ -86,6 +154,157 @@ except with duplicate types removed.
86154</p >
87155</blockquote >
88156</li >
157+
158+ <li >
159+ Change <sref ref =" [exec.let]" /> as indicated:
160+
161+ <blockquote >
162+ <p >
163+ -6-
164+ Let <i >`receiver2`</i > denote the following exposition-only class template:
165+ <pre ><code > namespace std::execution {
166+ &hello;
167+ }
168+ </code ></pre >
169+ Invocation of the function <code ><i >receiver2</i >::get_env</code >
170+ returns an object `e` such that
171+ <ol style =" list-style-type:none" >
172+ <li >(6.1) —
173+ `decltype(e)` models <i >`queryable`</i > and
174+ </li >
175+ <li >(6.2) —
176+ given a query object `q`, the expression `e.query(q)` is expression-equivalent
177+ to
178+ <code ><i >env</i >.query(q)</code >
179+ if that expression is valid<del >,</del ><ins >;</ins >
180+ otherwise,
181+ <ins >if the type of `q` satisfies <i >`forwarding-query`</i >,</ins >
182+ `e.query(q)` is expression-equivalent to
183+ <code >get_env(<i >rcvr</i >).query(q)</code >
184+ <ins >; otherwise, `e.query(q)` is ill-formed</ins >.
185+ </li >
186+ </ol >
187+ </p >
188+ <p >
189+ -7-
190+ <code ><i >impls-for</i >< <i >decayed-typeof</i >< <i >let-cpo</i >>> ::<i >get-state</i ></code >
191+ is initialized with a callable object [… ]
192+ </p >
193+ <p >
194+ -8-
195+ Let `Sigs` be a pack of the arguments to the `completion_signatures`
196+ specialization named by
197+ <code >completion_signatures_of_t< <i >child-type</i >< Sndr> ,
198+ <ins ><i >FWD-ENV-T</i >(</ins >env_of_t< Rcvr> <ins >)</ins >> </code >.
199+ Let `LetSigs` be a pack of those types in `Sigs` with a return type of
200+ <code ><i >decayed-typeof</i >< <i >set-cpo</i >> </code >.
201+ Let `as-tuple` be an alias template such that
202+ <code ><i >as-tuple</i >< Tag(Args...)> </code >
203+ denotes the type <code ><i >decayed-tuple</i >< Args...> </code >.
204+ Then `args_variant_t` denotes the type
205+ <code >variant< monostate, <i >as-tuple</i >< LetSigs> ...> </code >
206+ except with duplicate types removed.
207+ </p >
208+ </blockquote >
209+ </li >
210+
211+ <li >
212+ Change <sref ref =" [exec.when.all]" /> as indicated:
213+
214+ <blockquote >
215+ <p >
216+ -6-
217+ The member <code >impls-for< when_all_t> ::<i >get-env</i ></code >
218+ is initialized with a callable object equivalent to the following lambda
219+ expression:
220+ <pre ><code > []< class State, class Rcvr> (auto&& , State& state, const Receiver& rcvr) noexcept {
221+ return <i >see below</i >;
222+ }
223+ </code ></pre >
224+ Returns an object `e` such that
225+ <ol style =" list-style-type:none" >
226+ <li >(6.1) — `decltype(e)` models <i >`queryable`</i >, and</li >
227+ <li >(6.2) — `e.query(get_stop_token)` is expression-equivalent to
228+ <code >state.<i >stop-src</i >.get_token()</code >, and</li >
229+ <li >(6.3) —
230+ given a query object `q` with type other than <i >cv</i > `stop_token_t`
231+ <ins >and whose type satisfies <i >`forwarding-query`</i ></ins >,
232+ `e.query(q)` is expression-equivalent to `get_env(rcvr).query(q)`.
233+ </li >
234+ </ol >
235+ </p >
236+ <p >
237+ -7-
238+ The member <code ><i >impls-for</i >< when_all_t> ::<i >get-state</i ></code >
239+ is initialized with a callable object equivalent to the following
240+ lambda expression:
241+ <pre ><code > []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept(e) -> decltype(e) {
242+ return <i >e</i >;
243+ }
244+ </code ></pre >
245+ where <i >e</i > is the expression
246+ <pre ><code > std::forward< Sndr> (sndr).apply(<i >make-state</i >< Rcvr> ())
247+ </code ></pre >
248+ and <i >`make-state`</i > is the following exposition-only class template:
249+ <pre ><code > template< class Sndr, class Env>
250+ concept max-1-sender-in = sender_in< Sndr, Env> && <i >// exposition only</i >
251+ (tuple_size_v< value_types_of_t< Sndr, Env, tuple, tuple>> < = 1);
252+
253+ enum class <i >disposition</i > { <i >started</i >, <i >error</i >, <i >stopped</i > }; <i >// exposition only</i >
254+
255+ template< class Rcvr>
256+ struct make-state {
257+ template< max-1-sender-in< <ins ><i >FWD-ENV-T</i >(</ins >env_of_t< Rcvr> <ins >)</ins >> ... Sndrs>
258+ </code ></pre >
259+ …
260+ </p >
261+ <p >
262+ -8- Let <i >`copy_fail`</i > be `exception_ptr` if [… ]
263+ </p >
264+ <p >
265+ -9-
266+ The alias `values_tuple` denotes the type
267+ <pre ><code > tuple< value_types_of_t< Sndrs, <ins ><i >FWD-ENV-T</i >(</ins >env_of_t< Rcvr> <ins >)</ins >, <i >decayed-tuple</i >, optional> ...>
268+ </code ></pre >
269+ if that type is well-formed; otherwise, <code >tuple<> </code >.
270+ </p >
271+ </blockquote >
272+ </li >
273+
274+ <li >
275+ Change <sref ref =" [exec.into.variant]" /> as indicated:
276+
277+ <blockquote >
278+ -5-
279+ The member <code >impls-for< into_variant_t> ::<i >get-state</i ></code >
280+ is initialized with a callable object equivalent to the following lambda:
281+ <pre ><code > []< class Sndr, class Rcvr> (Sndr&& sndr, Rcvr& rcvr) noexcept
282+ -> type_identity< value_types_of_t< <i >child-type</i >< Sndr> , <ins ><i >FWD-ENV-T</i >(</ins >env_of_t< Rcvr> <ins >)</ins >>> {
283+ return {};
284+ }
285+ </code ></pre >
286+ </blockquote >
287+ </li >
288+
289+ <li >
290+ Change <sref ref =" [exec.stopped.opt]" /> as indicated:
291+
292+ <blockquote >
293+ -3-
294+ Let `sndr` and `env` be subexpressions such that `Sndr` is `decltype((sndr))`
295+ and `Env` is `decltype((env))`.
296+ If <code ><i >sender-for</i >< Sndr, stopped_as_optional_t> </code > is `false`,
297+ or if the type <code ><i >single-sender-value-type</i >< <ins ><i >child-type</i >< </ins >Sndr<ins >> </ins >, <ins ><i >FWD-ENV-T</i >(</ins >Env<ins >)</ins >> </code >
298+ is ill-formed or `void`,
299+ then the expression `stopped_as_optional.transform_sender(sndr, env)`
300+ is ill-formed; otherwise, it is equivalent to:
301+ <pre ><code > auto&& [_, _, child] = sndr;
302+ using V = <i >single-sender-value-type</i >< <ins ><i >child-type</i >< </ins >Sndr<ins >> </ins >, <ins ><i >FWD-ENV-T</i >(</ins >Env<ins >)</ins >> ;
303+ </code ></pre >
304+ …
305+ </blockquote >
306+ </li >
307+
89308</ol >
90309
91310</resolution >
0 commit comments