From 1b3c9b2b2f9be50d086f2cf2290d1d850224170d Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Tue, 3 Mar 2026 09:56:06 -0800 Subject: [PATCH] use the updated env when computing the final sender's completions --- include/stdexec/__detail/__finally.hpp | 72 ++++++++++++++------------ 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/include/stdexec/__detail/__finally.hpp b/include/stdexec/__detail/__finally.hpp index 394db417f..fd00a9763 100644 --- a/include/stdexec/__detail/__finally.hpp +++ b/include/stdexec/__detail/__finally.hpp @@ -44,29 +44,28 @@ namespace STDEXEC struct __finally_t { - template + template constexpr auto operator()(_Initial&& __initial, _Final&& __final) const // - -> STDEXEC::__well_formed_sender auto + -> __well_formed_sender auto { - return STDEXEC::__make_sexpr<__finally_t>({}, - static_cast<_Initial&&>(__initial), - static_cast<_Final&&>(__final)); + return __make_sexpr<__finally_t>({}, + static_cast<_Initial&&>(__initial), + static_cast<_Final&&>(__final)); } - template + template STDEXEC_ATTRIBUTE(always_inline) constexpr auto operator()(_Final&& __final) const { - return STDEXEC::__closure(*this, static_cast<_Final&&>(__final)); + return __closure(*this, static_cast<_Final&&>(__final)); } template - static constexpr auto - transform_sender(STDEXEC::set_value_t, _Sender&& __sndr, STDEXEC::__ignore) + static constexpr auto transform_sender(set_value_t, _Sender&& __sndr, __ignore) { auto& [__tag, __ign, __initial, __final] = __sndr; - return STDEXEC::__final::__sender{STDEXEC::__forward_like<_Sender>(__initial), // - STDEXEC::__forward_like<_Sender>(__final)}; + return __final::__sender{STDEXEC::__forward_like<_Sender>(__initial), // + STDEXEC::__forward_like<_Sender>(__final)}; } }; @@ -122,19 +121,27 @@ namespace STDEXEC template constexpr void operator()(_Receiver& __rcvr, _Tuple&& __tuple) noexcept { - STDEXEC::__apply(__applier{}, static_cast<_Tuple&&>(__tuple), __rcvr); + __apply(__applier{}, static_cast<_Tuple&&>(__tuple), __rcvr); } }; + using __mk_secondary_env_t = __mk_secondary_env_t; + + template + using __env2_t = __call_result_t<__mk_secondary_env_t, _CvInitialSender, _ReceiverEnv>; + + template + using __final_env_t = __join_env_t<_Env2 const &, __fwd_env_t<_ReceiverEnv>>; + template struct __final_receiver { using receiver_concept = receiver_t; - using __env2_t = __join_env_t<_Env2 const &, __fwd_env_t>>; + using __env_t = __final_env_t<_Env2, env_of_t<_Receiver>>; constexpr void set_value() noexcept { - STDEXEC::__visit(__visitor{}, std::move(__opstate_->__result_), __opstate_->__rcvr_); + __visit(__visitor{}, std::move(__opstate_->__result_), __opstate_->__rcvr_); } template @@ -150,7 +157,7 @@ namespace STDEXEC } [[nodiscard]] - constexpr auto get_env() const noexcept -> __env2_t + constexpr auto get_env() const noexcept -> __env_t { return __env::__join(__opstate_->__env2_, __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_))); } @@ -214,28 +221,18 @@ namespace STDEXEC template struct __initial_receiver; - template + template using __final_opstate_t = __final_opstate<_CvFinalSender, __result_variant_t<_CvInitialSender, _CvFinalSender, _Receiver>, _Receiver, - _Env2>; - - using __mk_secondary_env_t = - STDEXEC::__mk_secondary_env_t; - - template - using __env2_t = __call_result_t<__mk_secondary_env_t, _CvInitialSender, env_of_t<_Receiver>>; + __env2_t<_CvInitialSender, env_of_t<_Receiver>>>; template - struct __opstate - : __final_opstate_t<_CvInitialSender, - _CvFinalSender, - _Receiver, - __env2_t<_CvInitialSender, _Receiver>> + struct __opstate : __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver> { - using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>; - using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver, __env2_t>; + using __env2_t = __final::__env2_t<_CvInitialSender, env_of_t<_Receiver>>; + using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>; using __initial_results_t = __base_t::__results_t; constexpr explicit __opstate(_CvInitialSender&& __initial, @@ -303,17 +300,22 @@ namespace STDEXEC __final_opstate<_CvFinalSender, _ResultType, _Receiver, _Env2>* __opstate_; }; + template + using __mk_final_env_t = __final_env_t<__env2_t<_CvInitialSender, _Env>, _Env>; + template consteval auto __get_completion_signatures() { STDEXEC_COMPLSIGS_LET(__initial_completions, - STDEXEC::get_completion_signatures<_CvInitialSender, _Env...>()) + get_completion_signatures<_CvInitialSender, _Env...>()) { using __initial_completions_t = decltype(__initial_completions); auto __final_completions = - STDEXEC::get_completion_signatures<_CvFinalSender, __fwd_env_t<_Env>...>(); + get_completion_signatures<_CvFinalSender, __mk_final_env_t<_CvInitialSender, _Env>...>(); - if constexpr (!__sends...>) + if constexpr (__never_sends...>) { // If the finally sender doesn't have set_value completions, then we // don't need to worry about the initial sender's value types not being @@ -325,7 +327,9 @@ namespace STDEXEC {}, __final_completions); } - else if constexpr (!sender_of<_CvFinalSender, set_value_t(), __fwd_env_t<_Env>...>) + else if constexpr (!sender_of<_CvFinalSender, + set_value_t(), + __mk_final_env_t<_CvInitialSender, _Env>...>) { // If the finally sender has value completions other than set_value_t(), then // throw a compilation error.