From 7406b3056e09432758482437247f236b86f91425 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 24 May 2026 14:33:13 -0700 Subject: [PATCH 1/2] remove old `__gather_completion_signatures_t` utility --- include/exec/sequence/merge_each.hpp | 12 +-- include/exec/static_thread_pool.hpp | 2 +- include/nvexec/stream/when_all.cuh | 26 ++--- .../__detail/__completion_signatures.hpp | 2 +- .../__transform_completion_signatures.hpp | 94 +------------------ .../algos/adaptors/test_then_fail1.cpp | 3 +- 6 files changed, 21 insertions(+), 118 deletions(-) diff --git a/include/exec/sequence/merge_each.hpp b/include/exec/sequence/merge_each.hpp index ee099255b..b93366d51 100644 --- a/include/exec/sequence/merge_each.hpp +++ b/include/exec/sequence/merge_each.hpp @@ -857,15 +857,11 @@ namespace experimental::execution struct __gather_sequences_t { template - using __f = STDEXEC::__gather_completion_signatures_t< - _Completions, + using __f = STDEXEC::__gather_completions_t< STDEXEC::set_value_t, - // if set_value - __arg_of_t<_Sequence, _Sender, _Env...>::template __f, - // else remove - STDEXEC::__mconst>::__f, - // concat to __mlist result - STDEXEC::__mtry>>::__f>; + _Completions, + __arg_of_t<_Sequence, _Sender, _Env...>, + STDEXEC::__mtry>>>; }; template diff --git a/include/exec/static_thread_pool.hpp b/include/exec/static_thread_pool.hpp index b78e1bbf2..5f18060f7 100644 --- a/include/exec/static_thread_pool.hpp +++ b/include/exec/static_thread_pool.hpp @@ -1196,7 +1196,7 @@ namespace experimental::execution struct _static_thread_pool::_opstate : task_base { private: - friend struct ::exec::_pool_::_static_thread_pool::scheduler::_sender; + friend class ::exec::_pool_::_static_thread_pool::scheduler::_sender; explicit _opstate(_static_thread_pool& pool, remote_queue* queue, diff --git a/include/nvexec/stream/when_all.cuh b/include/nvexec/stream/when_all.cuh index efa005e18..cff4f50aa 100644 --- a/include/nvexec/stream/when_all.cuh +++ b/include/nvexec/stream/when_all.cuh @@ -160,13 +160,6 @@ namespace nv::execution::_strm } private: - template - using sends_values_t = __gather_completion_signatures_t>::__f, - __mconst<__mbool>::__f, - __mor_t>; - struct attrs { template @@ -308,13 +301,14 @@ namespace nv::execution::_strm exit_opstate_t<__copy_cvref_t<_when_all_sender_t, Sender>, receiver>; // tuple, tuple, ...> - using _child_values_t = __if, - __minvoke<__qq<__tuple>, - __value_types_of_t, - __qq<__decayed_tuple>, - __msingle_or>...>, - __>; + using _child_values_t = + __if_c != 0, + __minvoke<__qq<__tuple>, + __value_types_of_t, + __qq<__decayed_tuple>, + __msingle_or>...>, + __>; using _errors_t = error_types_of_t, __uniqued_variant>; @@ -394,7 +388,7 @@ namespace nv::execution::_strm switch (state_.load(std::memory_order_relaxed)) { case _when_all::started: - if constexpr (sends_values_t<_completions_t>::value) + if constexpr (STDEXEC::__detail::__count_of != 0) { // All child operations completed successfully: STDEXEC::__apply( @@ -462,7 +456,7 @@ namespace nv::execution::_strm template void _set_value(Args&&... args) noexcept { - if constexpr (sends_values_t<_completions_t>::value) + if constexpr (STDEXEC::__detail::__count_of != 0) { // We only need to bother recording the completion values // if we're not already in the "error" or "stopped" state. diff --git a/include/stdexec/__detail/__completion_signatures.hpp b/include/stdexec/__detail/__completion_signatures.hpp index 055b58344..c67e978a8 100644 --- a/include/stdexec/__detail/__completion_signatures.hpp +++ b/include/stdexec/__detail/__completion_signatures.hpp @@ -500,7 +500,7 @@ namespace STDEXEC } //////////////////////////////////////////////////////////////////////////////////////////////////// - // __gather_completion_signatures_t + // __gather_completions_t namespace __detail { template diff --git a/include/stdexec/__detail/__transform_completion_signatures.hpp b/include/stdexec/__detail/__transform_completion_signatures.hpp index 3e78641d9..fd3c41ad6 100644 --- a/include/stdexec/__detail/__transform_completion_signatures.hpp +++ b/include/stdexec/__detail/__transform_completion_signatures.hpp @@ -179,90 +179,6 @@ namespace STDEXEC _ErrorTransform, _StoppedSigs>; - ////////////////////////////////////////////////////////////////////////////////////////////////// - // __gather_completion_signatures_t - namespace __cmplsigs - { - template - struct __gather_sigs_fn; - - template <> - struct __gather_sigs_fn - { - template class _Then, - template class _Else, - template class _Variant, - class... _More> - using __f = __transform_reduce_completion_signatures_t< - _Sigs, - _Then, - __mbind_front_q<_Else, set_error_t>::template __f, - _Else, - _Variant, - _More...>; - }; - - template <> - struct __gather_sigs_fn - { - template class _Then, - template class _Else, - template class _Variant, - class... _More> - using __f = __transform_reduce_completion_signatures_t< - _Sigs, - __mbind_front_q<_Else, set_value_t>::template __f, - _Then, - _Else, - _Variant, - _More...>; - }; - - template <> - struct __gather_sigs_fn - { - template class _Then, - template class _Else, - template class _Variant, - class... _More> - using __f = __transform_reduce_completion_signatures_t< - _Sigs, - __mbind_front_q<_Else, set_value_t>::template __f, - __mbind_front_q<_Else, set_error_t>::template __f, - _Then<>, - _Variant, - _More...>; - }; - - template - struct __gather_sigs_fn<_WantedTag, false> - { - template class, - template class, - template class, - class...> - using __f = _Error; - }; - } // namespace __cmplsigs - - template class _Then, - template class _Else, - template class _Variant, - class... _More> - using __gather_completion_signatures_t = // - __cmplsigs::__gather_sigs_fn<_WantedTag, __ok<_Sigs>>::template __f< // - _Sigs, - _Then, - _Else, - _Variant, - _More...>; - ////////////////////////////////////////////////////////////////////////////////////////////////// // begin implementation of __transform_completion_signatures struct _IN_TRANSFORM_COMPLETION_SIGNATURES_; @@ -598,12 +514,10 @@ namespace STDEXEC template using __with_error_invoke_t = - __if<__gather_completion_signatures_t< - __completion_signatures_of_t<_Sender, _Env...>, - _Tag, - __mbind_front<__mtry_catch_q<__nothrow_invocable_t, _Catch>, _Fun>::template __f, - __mconst<__mbool>::__f, - __mand>, + __if<__gather_completions_t<_Tag, + __completion_signatures_of_t<_Sender, _Env...>, + __mbind_front<__mtry_catch_q<__nothrow_invocable_t, _Catch>, _Fun>, + __qq<__mand>>, completion_signatures<>, __eptr_completion_t>; diff --git a/test/stdexec/algos/adaptors/test_then_fail1.cpp b/test/stdexec/algos/adaptors/test_then_fail1.cpp index 3fe0e892b..b675a1b2f 100644 --- a/test/stdexec/algos/adaptors/test_then_fail1.cpp +++ b/test/stdexec/algos/adaptors/test_then_fail1.cpp @@ -20,7 +20,6 @@ namespace ex = STDEXEC; auto main() -> int { - ex::sender auto snd = ex::just(42) | ex::then([](int*) {}); // build error: _FUNCTION_IS_NOT_CALLABLE_WITH_THE_GIVEN_ARGUMENTS_.*_WITH_FUNCTION_.*_WITH_ARGUMENTS_ - STDEXEC::sync_wait(std::move(snd)); + ex::sender auto snd = ex::just(42) | ex::then([](int*) {}); } From 10947631cd2261d867081c00d6e0021d85516ceb Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 24 May 2026 18:39:13 -0700 Subject: [PATCH 2/2] try to fix broken compilers --- include/stdexec/__detail/__config.hpp | 6 +-- include/stdexec/__detail/__then.hpp | 39 ++++++++++----- .../__transform_completion_signatures.hpp | 2 +- include/stdexec/__detail/__upon_error.hpp | 48 ++++++++++++++----- include/stdexec/__detail/__upon_stopped.hpp | 23 ++++----- 5 files changed, 74 insertions(+), 44 deletions(-) diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 8a7b9c01f..c7e5d3605 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -855,21 +855,21 @@ namespace STDEXEC # define STDEXEC_EXPLICIT_THIS_END(_NAME) \ template \ STDEXEC_ATTRIBUTE(always_inline, host, device) \ - auto _NAME(_Ts&&... __args) && STDEXEC_AUTO_RETURN \ + constexpr auto _NAME(_Ts&&... __args) && STDEXEC_AUTO_RETURN \ ( \ STDEXEC_EXPLICIT_THIS_MANGLE(_NAME)(std::move(*this), static_cast<_Ts&&>(__args)...) \ ) \ \ template \ STDEXEC_ATTRIBUTE(always_inline, host, device) \ - auto _NAME(_Ts&&... __args) & STDEXEC_AUTO_RETURN \ + constexpr auto _NAME(_Ts&&... __args) & STDEXEC_AUTO_RETURN \ ( \ STDEXEC_EXPLICIT_THIS_MANGLE(_NAME)(*this, static_cast<_Ts&&>(__args)...) \ ) \ \ template \ STDEXEC_ATTRIBUTE(always_inline, host, device) \ - auto _NAME(_Ts&&... __args) const & STDEXEC_AUTO_RETURN \ + constexpr auto _NAME(_Ts&&... __args) const & STDEXEC_AUTO_RETURN \ ( \ STDEXEC_EXPLICIT_THIS_MANGLE(_NAME)(*this, static_cast<_Ts&&>(__args)...) \ ) diff --git a/include/stdexec/__detail/__then.hpp b/include/stdexec/__detail/__then.hpp index 7319eb31a..882dbfa0b 100644 --- a/include/stdexec/__detail/__then.hpp +++ b/include/stdexec/__detail/__then.hpp @@ -34,14 +34,6 @@ namespace STDEXEC // [execution.senders.adaptors.then] namespace __then { - using __on_not_callable = __mbind_front_q<__callable_error_t, then_t>; - - template - using __completions_t = __transform_completion_signatures_t< - __completion_signatures_of_t<_CvSender, _Env...>, - __with_error_invoke_t<__on_not_callable, set_value_t, _Fun, _CvSender, _Env...>, - __mbind_front<__mtry_catch_q<__set_value_from_t, __on_not_callable>, _Fun>::template __f>; - struct __then_impl : __sexpr_defaults { static constexpr auto __get_attrs = @@ -50,13 +42,36 @@ namespace STDEXEC return __sync_attrs{__child}; }; + template + static consteval auto __transform_value_completion() noexcept + { + return []() + { + if constexpr (__nothrow_invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>>(); + } + else if constexpr (__invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>, + set_error_t(std::exception_ptr)>(); + } + else + { + return STDEXEC::__throw_compile_time_error( + __callable_error_t()); + } + }; + } + template - static consteval auto __get_completion_signatures() // - -> __completions_t<__decay_t<__data_of<_Sender>>, __child_of<_Sender>, _Env...> + static consteval auto __get_completion_signatures() { static_assert(__sender_for<_Sender, then_t>); - // TODO: update this to use constant evaluation: - return {}; + using __fn_t = __decay_t<__data_of<_Sender>>; + return STDEXEC::__transform_completion_signatures( + STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), + __transform_value_completion<__fn_t>()); }; struct __complete_fn diff --git a/include/stdexec/__detail/__transform_completion_signatures.hpp b/include/stdexec/__detail/__transform_completion_signatures.hpp index fd3c41ad6..37e4bce1f 100644 --- a/include/stdexec/__detail/__transform_completion_signatures.hpp +++ b/include/stdexec/__detail/__transform_completion_signatures.hpp @@ -207,7 +207,7 @@ namespace STDEXEC template using __transform_expr_t = - decltype(__cmplsigs::__transform_expr<_Args...>(__declval<_Fn const &>(), 0)); + __decay_t(__declval<_Fn const &>(), 0))>; template [[nodiscard]] diff --git a/include/stdexec/__detail/__upon_error.hpp b/include/stdexec/__detail/__upon_error.hpp index e418f11a7..e511b5d47 100644 --- a/include/stdexec/__detail/__upon_error.hpp +++ b/include/stdexec/__detail/__upon_error.hpp @@ -21,6 +21,7 @@ #include "__completion_signatures_of.hpp" #include "__diagnostics.hpp" #include "__meta.hpp" +#include "__queries.hpp" #include "__sender_adaptor_closure.hpp" #include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender #include "__transform_completion_signatures.hpp" @@ -33,24 +34,45 @@ namespace STDEXEC // [execution.senders.adaptors.upon_error] namespace __upon_error { - using __on_not_callable = __mbind_front_q<__callable_error_t, upon_error_t>; - - template - using __completion_signatures_t = __transform_completion_signatures_t< - __completion_signatures_of_t<_CvSender, _Env...>, - __with_error_invoke_t<__on_not_callable, set_error_t, _Fun, _CvSender, _Env...>, - __cmplsigs::__default_set_value, - __mbind_front<__mtry_catch_q<__set_value_from_t, __on_not_callable>, _Fun>::template __f>; - struct __upon_error_impl : __sexpr_defaults { + static constexpr auto __get_attrs = + [](__ignore, __ignore, _Child const & __child) noexcept + { + return __sync_attrs{__child}; + }; + + template + static consteval auto __transform_error_completion() noexcept + { + return []() + { + if constexpr (__nothrow_invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>>(); + } + else if constexpr (__invocable<_Fun, _Args...>) + { + return completion_signatures<__single_value_sig_t<__invoke_result_t<_Fun, _Args...>>, + set_error_t(std::exception_ptr)>(); + } + else + { + return STDEXEC::__throw_compile_time_error( + __callable_error_t()); + } + }; + } + template - static consteval auto __get_completion_signatures() // - -> __completion_signatures_t<__decay_t<__data_of<_Sender>>, __child_of<_Sender>, _Env...> + static consteval auto __get_completion_signatures() { static_assert(__sender_for<_Sender, upon_error_t>); - // TODO: update this to use constant evaluation: - return {}; + using __fn_t = __decay_t<__data_of<_Sender>>; + return STDEXEC::__transform_completion_signatures( + STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), + {}, + __transform_error_completion<__fn_t>()); }; static constexpr auto __complete = diff --git a/include/stdexec/__detail/__upon_stopped.hpp b/include/stdexec/__detail/__upon_stopped.hpp index 34b3ebfc8..82a07c0d1 100644 --- a/include/stdexec/__detail/__upon_stopped.hpp +++ b/include/stdexec/__detail/__upon_stopped.hpp @@ -19,7 +19,6 @@ #include "__basic_sender.hpp" #include "__completion_signatures_of.hpp" -#include "__diagnostics.hpp" #include "__meta.hpp" #include "__sender_adaptor_closure.hpp" #include "__senders.hpp" // IWYU pragma: keep for __well_formed_sender @@ -33,25 +32,19 @@ namespace STDEXEC // [execution.senders.adaptors.upon_stopped] namespace __upon_stopped { - using __on_not_callable = __mbind_front_q<__callable_error_t, upon_stopped_t>; - - template - using __completion_signatures_t = __transform_completion_signatures_t< - __completion_signatures_of_t<_CvSender, _Env...>, - __with_error_invoke_t<__on_not_callable, set_stopped_t, _Fun, _CvSender, _Env...>, - __cmplsigs::__default_set_value, - __cmplsigs::__default_set_error, - __set_value_from_t<_Fun>>; - struct __upon_stopped_impl : __sexpr_defaults { template - static consteval auto __get_completion_signatures() // - -> __completion_signatures_t<__decay_t<__data_of<_Sender>>, __child_of<_Sender>, _Env...> + static consteval auto __get_completion_signatures() { static_assert(__sender_for<_Sender, upon_stopped_t>); - // TODO: update this to use constant evaluation: - return {}; + using __fn_t = __decay_t<__data_of<_Sender>>; + return STDEXEC::__transform_completion_signatures( + STDEXEC::get_completion_signatures<__child_of<_Sender>, _Env...>(), + {}, + {}, + __always{__set_value_from_t<__fn_t>()}, + __eptr_completion_unless_t<__mbool<__nothrow_callable<__fn_t>>>()); }; static constexpr auto __complete =