@@ -178,55 +178,61 @@ namespace stdexec {
178178 _Sender,
179179 __env>>;
180180
181- #if STDEXEC_EDG()
182- // It requires some hoop-jumping to get the NVHPC compiler to report a meaningful
183- // diagnostic for SFINAE failures.
184- template <class _Sender >
185- auto __diagnose_error () {
186- if constexpr (!sender_in<_Sender, __env>) {
187- using _Completions = __completion_signatures_of_t <_Sender, __env>;
188- if constexpr (__merror<_Completions>) {
189- return _Completions ();
190- } else {
191- constexpr __mstring __diag =
192- " The stdexec::sender_in<Sender, Environment> concept check has failed." _mstr;
193- return __sync_wait_error<__diag, _Sender>();
194- }
195- } else if constexpr (!__valid_sync_wait_argument<_Sender>) {
196- return __sync_wait_error<__too_many_successful_completions_diag, _Sender>();
197- } else if constexpr (!sender_to<_Sender, __sync_receiver_for_t <_Sender>>) {
198- constexpr __mstring __diag =
199- " Failed to connect the given sender to sync_wait's internal receiver. "
200- " The stdexec::connect(Sender, Receiver) expression is ill-formed." _mstr;
201- return __sync_wait_error<__diag, _Sender>();
202- } else {
203- constexpr __mstring __diag = " Unknown concept check failure." _mstr;
204- return __sync_wait_error<__diag, _Sender>();
205- }
206- }
207-
208- template <class _Sender >
209- using __error_description_t = decltype (__sync_wait::__diagnose_error<_Sender>());
210- #endif
211-
212181 // //////////////////////////////////////////////////////////////////////////
213182 // [execution.senders.consumers.sync_wait]
214183 struct sync_wait_t {
215- template <sender_in<__env> _Sender>
216- requires __valid_sync_wait_argument<_Sender>
217- && __has_implementation_for<sync_wait_t , __early_domain_of_t <_Sender>, _Sender>
218- auto operator ()(_Sender&& __sndr) const -> std::optional<__value_tuple_for_t<_Sender>> {
219- using _Domain = __late_domain_of_t <_Sender, __env>;
220- return stdexec::apply_sender (_Domain (), *this , static_cast <_Sender&&>(__sndr));
184+ template <class _Sender >
185+ auto operator ()(_Sender&& __sndr) const {
186+ if constexpr (!sender_in<_Sender, __env>) {
187+ stdexec::__diagnose_sender_concept_failure<_Sender, __env>();
188+ } else {
189+ using __domain_t = __late_domain_of_t <_Sender, __env>;
190+ constexpr auto __success_completion_count =
191+ __v<value_types_of_t <_Sender, __env, __types, __msize::__f>>;
192+ static_assert (
193+ __success_completion_count != 0 ,
194+ " The argument to stdexec::sync_wait() is a sender that cannot complete successfully. "
195+ " stdexec::sync_wait() requires a sender that can complete successfully in exactly one "
196+ " way. In other words, the sender's completion signatures must include exactly one "
197+ " signature of the form `set_value_t(value-types...)`." );
198+ static_assert (
199+ __success_completion_count <= 1 ,
200+ " The sender passed to stdexec::sync_wait() can complete successfully in "
201+ " more than one way. Use stdexec::sync_wait_with_variant() instead." );
202+ if constexpr (1 == __success_completion_count) {
203+ using __sync_wait_receiver = __receiver_t <_Sender>;
204+ constexpr bool __no_custom_sync_wait = __same_as<__domain_t , default_domain>;
205+ if constexpr (__no_custom_sync_wait && sender_to<_Sender, __sync_wait_receiver>) {
206+ // using __connect_result = connect_result_t<_Sender, __sync_wait_receiver>;
207+ // if constexpr (!operation_state<__connect_result>) {
208+ // static_assert(
209+ // operation_state<__connect_result>,
210+ // "The `connect` member function of the sender passed to stdexec::sync_wait() does "
211+ // "not return an operation state. An operation state is required to have a "
212+ // "no-throw .start() member function.");
213+ // } else
214+ {
215+ // success path, dispatch to the default domain's sync_wait
216+ return default_domain ().apply_sender (*this , static_cast <_Sender&&>(__sndr));
217+ }
218+ } else if constexpr (__no_custom_sync_wait) {
219+ static_assert (
220+ sender_to<_Sender, __sync_wait_receiver>,
221+ " The sender passed to stdexec::sync_wait() does not have a .connect(<receiver>) "
222+ " member function that accepts sync_wait's receiver." );
223+ } else if constexpr (!__has_implementation_for<sync_wait_t , __domain_t , _Sender>) {
224+ static_assert (
225+ __has_implementation_for<sync_wait_t , __domain_t , _Sender>,
226+ " The sender passed to stdexec::sync_wait() has a domain that does not provide a "
227+ " usable implementation for sync_wait()." );
228+ } else {
229+ // success path, dispatch to the custom domain's sync_wait
230+ return stdexec::apply_sender (__domain_t (), *this , static_cast <_Sender&&>(__sndr));
231+ }
232+ }
233+ }
221234 }
222235
223- #if STDEXEC_EDG()
224- // This is needed to get sensible diagnostics from nvc++
225- template <class _Sender , class _Error = __error_description_t <_Sender>>
226- auto operator ()(_Sender&&, [[maybe_unused]] _Error __diagnostic = {}) const
227- -> std::optional<std::tuple<int>> = delete;
228- #endif
229-
230236 // clang-format off
231237 // / @brief Synchronously wait for the result of a sender, blocking the
232238 // / current thread.
0 commit comments