From 025c004f9d768bd02e526efb95a935e43ad9f695 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sat, 8 Aug 2026 19:35:23 -0700 Subject: [PATCH] back out pseudo-reflection-based `__completion_info` for now --- .../stdexec/__detail/__completion_info.hpp | 170 ------- .../__detail/__get_completion_signatures.hpp | 17 - include/stdexec/__detail/__let.hpp | 479 ++++++++---------- 3 files changed, 211 insertions(+), 455 deletions(-) delete mode 100644 include/stdexec/__detail/__completion_info.hpp diff --git a/include/stdexec/__detail/__completion_info.hpp b/include/stdexec/__detail/__completion_info.hpp deleted file mode 100644 index ce5afb664..000000000 --- a/include/stdexec/__detail/__completion_info.hpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2026 NVIDIA Corporation - * - * Licensed under the Apache License Version 2.0 with LLVM Exceptions - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * https://llvm.org/LICENSE.txt - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#pragma once - -#include "__config.hpp" - -#if STDEXEC_USE_MODULES() && !defined(STDEXEC_IN_MODULE_PURVIEW) - -import stdexec; - -#else - -# include "__execution_fwd.hpp" - -// IWYU pragma: begin_keep -# include "__completion_behavior.hpp" -# include "__completion_signatures.hpp" -# include "__meta.hpp" -# include "__static_vector.hpp" -# include "__typeinfo.hpp" - -# include "../functional.hpp" -// IWYU pragma: end_keep - -# if !STDEXEC_USE_MODULES() -// IWYU pragma: begin_keep -# include -# include -# include -// IWYU pragma: end_keep -# endif - -# include "__prologue.hpp" - -namespace STDEXEC -{ - template - constexpr _Sig *__signature = nullptr; - - struct __completion_info - { - using __behavior_t = __completion_behavior::__behavior; - - STDEXEC::__disposition __disposition = __invalid_disposition; - __type_index __signature = __mtypeid; - __type_index __domain = __mtypeid; - __behavior_t __behavior = __completion_behavior::__unknown; - - __completion_info() = default; - - template <__completion_tag _Tag, class... _Args> - constexpr __completion_info(_Tag (*)(_Args...), - __type_index __domain = __mtypeid, - __behavior_t __behavior = __completion_behavior::__unknown) noexcept - : __disposition(_Tag::__disposition) - , __signature(__mtypeid<_Tag(_Args...)>) - , __domain(__domain) - , __behavior(__behavior) - {} - - template - constexpr auto __populate() noexcept -> __completion_info & - { - switch (__disposition) - { - case __disposition::__value: - __domain = __mtypeid<__completion_domain_t, _Env...>>; - __behavior = STDEXEC::__get_completion_behavior(); - break; - case __disposition::__error: - __domain = __mtypeid<__completion_domain_t, _Env...>>; - __behavior = STDEXEC::__get_completion_behavior(); - break; - case __disposition::__stopped: - __domain = __mtypeid<__completion_domain_t, _Env...>>; - __behavior = STDEXEC::__get_completion_behavior(); - break; - } - return *this; - } - - [[nodiscard]] - constexpr auto operator<=>(__completion_info const &) const noexcept // - -> std::strong_ordering = default; - }; - - namespace __cmplsigs - { - template - constexpr auto __completion_info_from_v = []() noexcept - { - auto __cmpl_info = _GetComplInfo(); - STDEXEC_IF_OK(__cmpl_info) - { - constexpr auto __size = _GetComplInfo().size(); - auto __arr = __static_vector<__completion_info, __size>(); - std::ranges::sort(__cmpl_info); - auto const __end = std::ranges::unique_copy(__cmpl_info, __arr.begin()).out; - __arr.resize(__end - __arr.begin()); - return __arr; - } - }(); - - template - consteval auto __completion_info_from(_GetComplInfo) noexcept -> auto const & - { - return __completion_info_from_v<(_GetComplInfo())>; - } - - template - constexpr auto __completion_sigs_from_v = []() noexcept - { - constexpr auto __completions = __completion_info_from_v<_GetComplInfo>; - STDEXEC_IF_OK(__completions) - { - auto __signatures = __static_vector<__type_index, __completions.size()>(); - __signatures.resize(__completions.size()); - std::ranges::transform(__completions, - __signatures.begin(), - &__completion_info::__signature); - std::ranges::sort(__signatures); - auto const __end = std::ranges::unique(__signatures).begin(); - __signatures.erase(__end, __signatures.end()); - return __signatures; - } - }(); - - template - consteval auto __completion_sigs_splice(__indices<_Is...>) noexcept - { - return completion_signatures<__msplice<__sigs[_Is]>...>(); - } - - template - consteval auto __completion_sigs_from(_GetComplInfo) noexcept - { - constexpr auto __sigs = __completion_sigs_from_v<(_GetComplInfo())>; - STDEXEC_IF_OK(__sigs) - { - return __completion_sigs_splice<__sigs>(__make_indices<__sigs.size()>()); - } - } - - template - [[nodiscard]] - consteval auto __to_array(completion_signatures<_Sigs...>) noexcept - { - using __array_t = __static_vector<__completion_info, sizeof...(_Sigs)>; - auto __compls = __array_t{__completion_info(__signature<_Sigs>)...}; - std::ranges::sort(__compls); - return __compls; - } - } // namespace __cmplsigs -} // namespace STDEXEC - -# include "__epilogue.hpp" -#endif // !STDEXEC_USE_MODULES() || defined(STDEXEC_IN_MODULE_PURVIEW) diff --git a/include/stdexec/__detail/__get_completion_signatures.hpp b/include/stdexec/__detail/__get_completion_signatures.hpp index 2b0ecda65..5667de95c 100644 --- a/include/stdexec/__detail/__get_completion_signatures.hpp +++ b/include/stdexec/__detail/__get_completion_signatures.hpp @@ -27,7 +27,6 @@ import stdexec; // include these after __execution_fwd.hpp # include "__awaitable.hpp" -# include "__completion_info.hpp" # include "__completion_signatures.hpp" // IWYU pragma: export # include "__connect_awaitable.hpp" # include "__diagnostics.hpp" @@ -36,10 +35,6 @@ import stdexec; # include "__tag_invoke.hpp" # include "__tuple.hpp" // IWYU pragma: keep for __tuple -# if !STDEXEC_USE_MODULES() -# include -# endif - # include "__prologue.hpp" namespace STDEXEC @@ -512,18 +507,6 @@ namespace STDEXEC template using __count_of = __msize_t<__detail::__count_of<_Tag, __completion_signatures_of_t<_Sender, _Env...>>>; - - template - consteval auto __get_completion_info() - { - auto __cmplsigs = STDEXEC::get_completion_signatures<_Sender, _Env...>(); - STDEXEC_IF_OK(__cmplsigs) - { - auto __cmplinfo = STDEXEC::__cmplsigs::__to_array(__cmplsigs); - std::ranges::for_each(__cmplinfo, &__completion_info::__populate<_Sender, _Env...>); - return __cmplinfo; - } - } } // namespace STDEXEC # include "__epilogue.hpp" diff --git a/include/stdexec/__detail/__let.hpp b/include/stdexec/__detail/__let.hpp index 45b2950a6..9777fccc3 100644 --- a/include/stdexec/__detail/__let.hpp +++ b/include/stdexec/__detail/__let.hpp @@ -27,15 +27,14 @@ import stdexec; // include these after __execution_fwd.hpp # include "__basic_sender.hpp" -# include "__completion_info.hpp" # include "__diagnostics.hpp" -# include "__domain.hpp" # include "__env.hpp" # include "__meta.hpp" # include "__schedulers.hpp" # include "__sender_adaptor_closure.hpp" # include "__senders.hpp" # include "__submit.hpp" +# include "__transform_completion_signatures.hpp" # include "__utility.hpp" # include "__variant.hpp" @@ -111,7 +110,7 @@ namespace STDEXEC _Env...>; template - using __bad_result_sender = __mexception< + using __bad_result_sender_t = __mexception< _WHAT_(_FUNCTION_MUST_RETURN_A_VALID_SENDER_IN_THE_CURRENT_ENVIRONMENT_), _WHERE_(_IN_ALGORITHM_, _LetTag), _WITH_PRETTY_SENDER_<_Sender>, @@ -340,172 +339,172 @@ namespace STDEXEC __op_state_variant_t __storage_{__no_init}; }; - // The set_value completions of: - // - // * a let_value sender are: - // * the value completions of the secondary senders - // - // * a let_error sender are: - // * the value completions of the predecessor sender - // * the value completions of the secondary senders - // - // * a let_stopped sender are: - // * the value completions of the predecessor sender - // * the value completions of the secondary sender - // - // The set_error completions of: - // - // * a let_value sender are: - // * the error completions of the predecessor sender - // * the error completions of the secondary senders - // * the value completions of the predecessor sender if decay copying the arguments can throw - // - // * a let_error sender are: - // * the error completions of the secondary senders - // * the error completions of the predecessor sender if decay copying the errors can throw - // - // * a let_stopped sender are: - // * the error completions of the predecessor sender - // * the error completions of the secondary senders - // - // The set_stopped completions of: - // - // * a let_value sender are: - // * the stopped completions of the predecessor sender - // * the stopped completions of the secondary senders - // - // * a let_error sender are: - // * the stopped completions of the predecessor sender - // * the stopped completions of the secondary senders - // - // * a let_stopped sender are: - // * the stopped completions of the secondary sender - // - template - struct __result_completion_behavior_fn - { - template - [[nodiscard]] - static constexpr auto __impl() noexcept - { - using __sndr_t = - __minvoke_or_q<__invoke_result_t, __not_a_sender<>, _Fun, __decay_t<_Ts>&...>; - return STDEXEC::__get_completion_behavior<_SetTag, __sndr_t, _JoinEnv2...>(); - } - - template - using __f = decltype(__impl<_Ts...>()); - }; - - template - struct __domain_transform_fn - { - template - using __f = __completion_domain_of_t<_SetTag, - __invoke_result_t<_Fun, __decay_t<_As>&...>, - __result_env_t<_SetTag, _Sender, _Env>...>; - }; - - //! @tparam _LetTag The tag type for the let_ operation. - //! @tparam _SetTag The completion signal of the let_ sender itself that is being - //! queried. For example, you may be querying a let_value sender for its set_error - //! completion domain. - template - [[nodiscard]] - consteval auto __get_completion_domain() noexcept - { - if constexpr (sender_in<_Sndr, _Env...>) - { - using __domain_transform_fn = __let::__domain_transform_fn<_SetTag, _Fun, _Sndr, _Env...>; - return __minvoke_or_q<__gather_completions_t, - indeterminate_domain<>, - __t<_LetTag>, - __completion_signatures_of_t<_Sndr, _Env...>, - __domain_transform_fn, - __qq<__common_domain_t>>(); - } - else - { - return indeterminate_domain<>{}; - } - } - - template - using __let_completion_domain_t = __unless_one_of_t< - __result_of<__let::__get_completion_domain<_LetTag, _SetTag, _Sndr, _Fun, _Env...>>, - indeterminate_domain<>>; - - template - struct __attrs - { - using __set_tag_t = STDEXEC::__t<_LetTag>; - - template - constexpr auto query(get_completion_scheduler_t<_Tag>) const = delete; - - template - [[nodiscard]] - constexpr auto query(get_completion_domain_t<__set_tag_t>, _Env const &...) const noexcept - -> __ensure_valid_domain_t< - __let_completion_domain_t<_LetTag, __set_tag_t, _Sndr, _Fun, _Env...>> - { - return {}; - } - - template <__one_of _Tag, class... _Env> - requires(__has_nothrow_completions_t<__set_tag_t, _Sndr, _Fun, _Env>::value && ...) - [[nodiscard]] - constexpr auto query(get_completion_domain_t<_Tag>, _Env const &...) const noexcept - -> __ensure_valid_domain_t< - __common_domain_t<__completion_domain_of_t<_Tag, _Sndr, __fwd_env_t<_Env>...>, - __let_completion_domain_t<_LetTag, _Tag, _Sndr, _Fun, _Env...>>> - { - return {}; - } - - template - requires(!__has_nothrow_completions_t<__set_tag_t, _Sndr, _Fun, _Env>::value) - [[nodiscard]] - constexpr auto query(get_completion_domain_t, _Env const &) const noexcept - -> __ensure_valid_domain_t< - __common_domain_t<__completion_domain_of_t<__set_tag_t, _Sndr, __fwd_env_t<_Env>>, - __completion_domain_of_t>, - __let_completion_domain_t<_LetTag, set_error_t, _Sndr, _Fun, _Env>>> - { - return {}; - } - - template - [[nodiscard]] - constexpr auto query(__get_completion_behavior_t<__set_tag_t>, _Env const &...) const noexcept - { - if constexpr (sender_in<_Sndr, __fwd_env_t<_Env>...>) - { - // The completion behavior of let_value(sndr, fn) is the union of the completion - // behavior of sndr and all the senders that fn can potentially produce. (MSVC - // needs the constexpr computation broken up, hence the local variables.) - using __transform_fn = - __result_completion_behavior_fn<__set_tag_t, - _Fun, - __result_env_t<__set_tag_t, _Sndr, _Env>...>; - using __completions_t = __completion_signatures_of_t<_Sndr, __fwd_env_t<_Env>...>; - - constexpr auto __pred_behavior = - STDEXEC::__get_completion_behavior<__set_tag_t, _Sndr, __fwd_env_t<_Env>...>(); - constexpr auto __result_behaviors = __gather_completions_t< - __set_tag_t, - __completions_t, - __transform_fn, - __mbind_front_q<__call_result_t, __completion_behavior::__common_t>>(); - - return __pred_behavior | __result_behaviors; - } - else - { - return __completion_behavior::__unknown; - } - } - }; + // // The set_value completions of: + // // + // // * a let_value sender are: + // // * the value completions of the secondary senders + // // + // // * a let_error sender are: + // // * the value completions of the predecessor sender + // // * the value completions of the secondary senders + // // + // // * a let_stopped sender are: + // // * the value completions of the predecessor sender + // // * the value completions of the secondary sender + // // + // // The set_error completions of: + // // + // // * a let_value sender are: + // // * the error completions of the predecessor sender + // // * the error completions of the secondary senders + // // * the value completions of the predecessor sender if decay copying the arguments can throw + // // + // // * a let_error sender are: + // // * the error completions of the secondary senders + // // * the error completions of the predecessor sender if decay copying the errors can throw + // // + // // * a let_stopped sender are: + // // * the error completions of the predecessor sender + // // * the error completions of the secondary senders + // // + // // The set_stopped completions of: + // // + // // * a let_value sender are: + // // * the stopped completions of the predecessor sender + // // * the stopped completions of the secondary senders + // // + // // * a let_error sender are: + // // * the stopped completions of the predecessor sender + // // * the stopped completions of the secondary senders + // // + // // * a let_stopped sender are: + // // * the stopped completions of the secondary sender + // // + // template + // struct __result_completion_behavior_fn + // { + // template + // [[nodiscard]] + // static constexpr auto __impl() noexcept + // { + // using __sndr_t = + // __minvoke_or_q<__invoke_result_t, __not_a_sender<>, _Fun, __decay_t<_Ts>&...>; + // return STDEXEC::__get_completion_behavior<_SetTag, __sndr_t, _JoinEnv2...>(); + // } + + // template + // using __f = decltype(__impl<_Ts...>()); + // }; + + // template + // struct __domain_transform_fn + // { + // template + // using __f = __completion_domain_of_t<_SetTag, + // __invoke_result_t<_Fun, __decay_t<_As>&...>, + // __result_env_t<_SetTag, _Sender, _Env>...>; + // }; + + // //! @tparam _LetTag The tag type for the let_ operation. + // //! @tparam _SetTag The completion signal of the let_ sender itself that is being + // //! queried. For example, you may be querying a let_value sender for its set_error + // //! completion domain. + // template + // [[nodiscard]] + // consteval auto __get_completion_domain() noexcept + // { + // if constexpr (sender_in<_Sndr, _Env...>) + // { + // using __domain_transform_fn = __let::__domain_transform_fn<_SetTag, _Fun, _Sndr, _Env...>; + // return __minvoke_or_q<__gather_completions_t, + // indeterminate_domain<>, + // __t<_LetTag>, + // __completion_signatures_of_t<_Sndr, _Env...>, + // __domain_transform_fn, + // __qq<__common_domain_t>>(); + // } + // else + // { + // return indeterminate_domain<>{}; + // } + // } + + // template + // using __let_completion_domain_t = __unless_one_of_t< + // __result_of<__let::__get_completion_domain<_LetTag, _SetTag, _Sndr, _Fun, _Env...>>, + // indeterminate_domain<>>; + + // template + // struct __attrs + // { + // using __set_tag_t = STDEXEC::__t<_LetTag>; + + // template + // constexpr auto query(get_completion_scheduler_t<_Tag>) const = delete; + + // template + // [[nodiscard]] + // constexpr auto query(get_completion_domain_t<__set_tag_t>, _Env const &...) const noexcept + // -> __ensure_valid_domain_t< + // __let_completion_domain_t<_LetTag, __set_tag_t, _Sndr, _Fun, _Env...>> + // { + // return {}; + // } + + // template <__one_of _Tag, class... _Env> + // requires(__has_nothrow_completions_t<__set_tag_t, _Sndr, _Fun, _Env>::value && ...) + // [[nodiscard]] + // constexpr auto query(get_completion_domain_t<_Tag>, _Env const &...) const noexcept + // -> __ensure_valid_domain_t< + // __common_domain_t<__completion_domain_of_t<_Tag, _Sndr, __fwd_env_t<_Env>...>, + // __let_completion_domain_t<_LetTag, _Tag, _Sndr, _Fun, _Env...>>> + // { + // return {}; + // } + + // template + // requires(!__has_nothrow_completions_t<__set_tag_t, _Sndr, _Fun, _Env>::value) + // [[nodiscard]] + // constexpr auto query(get_completion_domain_t, _Env const &) const noexcept + // -> __ensure_valid_domain_t< + // __common_domain_t<__completion_domain_of_t<__set_tag_t, _Sndr, __fwd_env_t<_Env>>, + // __completion_domain_of_t>, + // __let_completion_domain_t<_LetTag, set_error_t, _Sndr, _Fun, _Env>>> + // { + // return {}; + // } + + // template + // [[nodiscard]] + // constexpr auto query(__get_completion_behavior_t<__set_tag_t>, _Env const &...) const noexcept + // { + // if constexpr (sender_in<_Sndr, __fwd_env_t<_Env>...>) + // { + // // The completion behavior of let_value(sndr, fn) is the union of the completion + // // behavior of sndr and all the senders that fn can potentially produce. (MSVC + // // needs the constexpr computation broken up, hence the local variables.) + // using __transform_fn = + // __result_completion_behavior_fn<__set_tag_t, + // _Fun, + // __result_env_t<__set_tag_t, _Sndr, _Env>...>; + // using __completions_t = __completion_signatures_of_t<_Sndr, __fwd_env_t<_Env>...>; + + // constexpr auto __pred_behavior = + // STDEXEC::__get_completion_behavior<__set_tag_t, _Sndr, __fwd_env_t<_Env>...>(); + // constexpr auto __result_behaviors = __gather_completions_t< + // __set_tag_t, + // __completions_t, + // __transform_fn, + // __mbind_front_q<__call_result_t, __completion_behavior::__common_t>>(); + + // return __pred_behavior | __result_behaviors; + // } + // else + // { + // return __completion_behavior::__unknown; + // } + // } + // }; //! Implementation of the `let_*_t` types, where `_SetTag` is, e.g., `set_value_t` for `let_value`. template @@ -554,112 +553,44 @@ namespace STDEXEC __mbind_front_q<__opstate, __set_t, __child_of<_CvSender>, __fn_t<_CvSender>, _Receiver>>; template - static constexpr auto __transform_cmplsig = // - [](__set_t (*)(_As...), __completion_info __info) // - -> decltype(auto) + static consteval auto __get_transform_fn() { - if constexpr (!__decay_copyable<_As...>) - { - using __what_t = __not_decay_copyable_error_t<_LetTag, _As...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else if constexpr (!__invocable<_Fun, __decay_t<_As>&...>) + return []() { - using __what_t = __callable_error_t<_LetTag, _Fun, __decay_t<_As>&...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else if constexpr (!__potentially_valid_sender_in< - __invoke_result_t<_Fun, __decay_t<_As>&...>, - __env2_t<_Child, _Env>...>) - { - using __sndr_t = __invoke_result_t<_Fun, __decay_t<_As>&...>; - using __what_t = __bad_result_sender<__sndr_t, _LetTag, __env2_t<_Child, _Env>...>; - return STDEXEC::__throw_compile_time_error(__what_t()); - } - else - { - using __sndr2_t = __invoke_result_t<_Fun, __decay_t<_As>&...>; - auto __cmpls = STDEXEC::__get_completion_info<__sndr2_t, __env2_t<_Child, _Env>...>(); - STDEXEC_IF_OK(__cmpls) + if constexpr (__decay_copyable<_Args...> && __invocable<_Fun, __decay_t<_Args>&...>) { - if constexpr (!__nothrow_decay_copyable<_As...> - || !__nothrow_invocable<_Fun, __decay_t<_As>&...> - || (!__nothrow_connectable<__sndr2_t, __rcvr2_t<_Child, _Env>> || ...)) + using __sndr2_t = __invoke_result_t<_Fun, __decay_t<_Args>&...>; + if constexpr (!__potentially_valid_sender_in<__sndr2_t, __env2_t<_Child, _Env>...>) + { + using __what_t = __bad_result_sender_t<__sndr2_t, _LetTag, __env2_t<_Child, _Env>...>; + return STDEXEC::__throw_compile_time_error(__what_t()); + } + else if constexpr (__nothrow_decay_copyable<_Args...> + && __nothrow_invocable<_Fun, __decay_t<_Args>&...> + && (__nothrow_connectable<__sndr2_t, __rcvr2_t<_Child, _Env>> + || ...)) { - __completion_info const __eptr_info(__signature<__eptr_sig_t>, - __info.__domain, - __info.__behavior); - return __cmpls + STDEXEC::__make_static_vector(__eptr_info); + return STDEXEC::get_completion_signatures<__sndr2_t, __env2_t<_Child, _Env>...>(); } else { - return __cmpls; + return STDEXEC::__concat_completion_signatures( + STDEXEC::get_completion_signatures<__sndr2_t, __env2_t<_Child, _Env>...>(), + __eptr_completion_t()); } } - } - }; - - template <__completion_info _Info> - static constexpr auto __maybe_transform_cmplsig = [](auto __transform) -> decltype(auto) - { - if constexpr (_Info.__disposition != __set_t::__disposition) - return STDEXEC::__make_static_vector(_Info); - else - return __transform(__signature<__msplice<_Info.__signature>>, _Info); - }; - - template - struct __cmpl_info_inner_fn - { - constexpr auto operator()() const - { - __static_vector<__completion_info, 0> __result; - return (__maybe_transform_cmplsig<_Info[_Is]>(_Transform) + ... + __result); - } - }; - - template - struct __cmpl_info_outer_fn - { - template - constexpr auto operator()(__indices<_Is...>) const - { - return __cmpl_info_inner_fn<_Info, _Transform, _Is...>{}; - } - }; - - //! @tparam _Info A `__static_vector` of `__completion_info` objects representing - //! the completions of the predecessor sender. - template - static constexpr auto __get_cmpl_info_i = __cmpl_info_outer_fn<_Info, _Transform>{}; - - template - struct __get_cmpl_info - { - constexpr auto operator()() const - { - constexpr auto __transform = __transform_cmplsig<_Fun, _Child, _Env...>; - constexpr auto __get_sig = &__completion_info::__signature; - constexpr auto __eptr_sig_id = __mtypeid<__eptr_sig_t>; - constexpr auto __cmpls = STDEXEC::__get_completion_info<_Child, _Env...>(); - - STDEXEC_IF_OK(__cmpls) + else if constexpr (__decay_copyable<_Args...>) { - constexpr auto __idx = __make_indices<__cmpls.size()>(); - constexpr auto __get_cmpls2 = __get_cmpl_info_i<__cmpls, __transform>(__idx); - constexpr auto __cmpls2 = __cmplsigs::__completion_info_from(__get_cmpls2); - - STDEXEC_IF_OK(__cmpls2) - { - if constexpr (std::ranges::find(__cmpls2, __eptr_sig_id, __get_sig) == __cmpls2.end() - && sizeof...(_Env) == 0) - return STDEXEC::__throw_dependent_sender_error<_Child>(); - else - return __cmpls2; - } + using __what_t = __callable_error_t<_LetTag, _Fun, __decay_t<_Args>&...>; + return STDEXEC::__throw_compile_time_error(__what_t()); } - } - }; + else + { + using __what_t = __not_decay_copyable_error_t<_LetTag, _Args...>; + return STDEXEC::__throw_compile_time_error(__what_t()); + } + }; + } public: static constexpr auto __get_attrs = @@ -673,14 +604,26 @@ namespace STDEXEC static consteval auto __get_completion_signatures() { static_assert(__sender_for<_CvSender, _LetTag>); - constexpr auto __get_cmpl_info = - __impls::__get_cmpl_info<__fn_t<_CvSender>, __child_of<_CvSender>, _Env...>(); - + using __child_t = __child_of<_CvSender>; + auto __completions = STDEXEC::get_completion_signatures<__child_t, _Env...>(); + auto __transform = __get_transform_fn<__fn_t<_CvSender>, __child_t, _Env...>(); if constexpr (!__decay_copyable<_CvSender>) + { return STDEXEC::__throw_compile_time_error<_SENDER_TYPE_IS_NOT_DECAY_COPYABLE_, _WITH_PRETTY_SENDER_<_CvSender>>(); + } + else if constexpr (__t<_LetTag>() == STDEXEC::set_value) + { + return STDEXEC::__transform_completion_signatures(__completions, __transform); + } + else if constexpr (__t<_LetTag>() == STDEXEC::set_error) + { + return STDEXEC::__transform_completion_signatures(__completions, {}, __transform); + } else - return __cmplsigs::__completion_sigs_from(__get_cmpl_info); + { + return STDEXEC::__transform_completion_signatures(__completions, {}, {}, __transform); + } } static constexpr auto __connect =