From 7bed4b454f34496794613bae63b77080ea52d842 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 2 Mar 2026 09:56:13 -0800 Subject: [PATCH 1/3] fix domain query of `__sched_env` --- include/stdexec/__detail/__schedulers.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index d27190a25..0c31f8dca 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -396,7 +396,7 @@ namespace STDEXEC } STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto query(get_domain_t) const noexcept -> __call_result_t + constexpr auto query(get_domain_t) const noexcept -> __detail::__scheduler_domain_t<_Scheduler> { return {}; } From 8434e7602e66a2b9112e9bd42bc3a3ee9934c91b Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 2 Mar 2026 13:51:44 -0800 Subject: [PATCH 2/3] fr --- include/stdexec/__detail/__finally.hpp | 64 ++++++--- include/stdexec/__detail/__let.hpp | 70 +++------- include/stdexec/__detail/__schedulers.hpp | 121 ++++++++++++++---- .../stdexec/__detail/__sender_concepts.hpp | 3 + include/stdexec/__detail/__starts_on.hpp | 2 +- include/stdexec/__detail/__transfer_just.hpp | 2 +- include/stdexec/__detail/__when_all.hpp | 4 +- 7 files changed, 166 insertions(+), 100 deletions(-) diff --git a/include/stdexec/__detail/__finally.hpp b/include/stdexec/__detail/__finally.hpp index 7eea6ea08..e67cc10a7 100644 --- a/include/stdexec/__detail/__finally.hpp +++ b/include/stdexec/__detail/__finally.hpp @@ -21,6 +21,7 @@ // include these after execution_fwd.hpp #include "__basic_sender.hpp" #include "__optional.hpp" +#include "__schedulers.hpp" #include "__sender_adaptor_closure.hpp" #include "__senders.hpp" #include "__transform_completion_signatures.hpp" @@ -64,8 +65,8 @@ namespace STDEXEC transform_sender(STDEXEC::set_value_t, _Sender&& __sndr, STDEXEC::__ignore) { auto& [__tag, __ign, __initial, __final] = __sndr; - return __final ::__sender{STDEXEC::__forward_like<_Sender>(__initial), // - STDEXEC::__forward_like<_Sender>(__final)}; + return STDEXEC::__final::__sender{STDEXEC::__forward_like<_Sender>(__initial), // + STDEXEC::__forward_like<_Sender>(__final)}; } }; @@ -98,10 +99,12 @@ namespace STDEXEC _CvInitialSender, _Receiver>; - template + template struct __opstate_base { _Receiver __rcvr_{}; + STDEXEC_ATTRIBUTE(no_unique_address) + _Env2 const __env2_{}; _ResultType __result_{__no_init}; // __variant<__tuple, ...> }; @@ -123,10 +126,11 @@ namespace STDEXEC } }; - template + template struct __final_receiver { using receiver_concept = receiver_t; + using __env2_t = __join_env_t<_Env2 const &, __fwd_env_t>>; constexpr void set_value() noexcept { @@ -146,26 +150,28 @@ namespace STDEXEC } [[nodiscard]] - constexpr auto get_env() const noexcept -> __fwd_env_t> + constexpr auto get_env() const noexcept -> __env2_t { - return __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_)); + return __env::__join(__opstate_->__env2_, __fwd_env(STDEXEC::get_env(__opstate_->__rcvr_))); } - __opstate_base<_ResultType, _Receiver>* __opstate_; + __opstate_base<_ResultType, _Receiver, _Env2>* __opstate_; }; - template - struct __final_opstate : __opstate_base<_ResultType, _Receiver> + template + struct __final_opstate : __opstate_base<_ResultType, _Receiver, _Env2> { using __results_t = _ResultType; using __cleanup_callback_t = void(__final_opstate*) noexcept; - using __final_receiver_t = __final_receiver<_ResultType, _Receiver>; + using __final_receiver_t = __final_receiver<_ResultType, _Receiver, _Env2>; using __final_opstate_t = connect_result_t<_CvFinalSender, __final_receiver_t>; constexpr explicit __final_opstate(__cleanup_callback_t* __cleanup_callback, _CvFinalSender&& __final, - _Receiver&& __rcvr) noexcept - : __opstate_base<_ResultType, _Receiver>{static_cast<_Receiver&&>(__rcvr)} + _Receiver&& __rcvr, + _Env2 __env2) noexcept + : __opstate_base<_ResultType, _Receiver, _Env2>{static_cast<_Receiver&&>(__rcvr), + static_cast<_Env2&&>(__env2)} , __cleanup_callback_{__cleanup_callback} , __final_opstate_( STDEXEC::connect(static_cast<_CvFinalSender&&>(__final), __final_receiver_t{this})) @@ -205,19 +211,33 @@ namespace STDEXEC __final_opstate_t __final_opstate_; }; - template + template struct __initial_receiver; - template + template using __final_opstate_t = __final_opstate<_CvFinalSender, __result_variant_t<_CvInitialSender, _CvFinalSender, _Receiver>, - _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>>; template - struct __opstate : __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver> + struct __opstate + : __final_opstate_t<_CvInitialSender, + _CvFinalSender, + _Receiver, + __env2_t<_CvInitialSender, _Receiver>> { - using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver>; + using __base_t = __final_opstate_t<_CvInitialSender, + _CvFinalSender, + _Receiver, + __env2_t<_CvInitialSender, _Receiver>>; using __initial_results_t = __base_t::__results_t; constexpr explicit __opstate(_CvInitialSender&& __initial, @@ -225,7 +245,8 @@ namespace STDEXEC _Receiver __rcvr) : __base_t(&__cleanup_initial_opstate, static_cast<_CvFinalSender&&>(__final), - static_cast<_Receiver&&>(__rcvr)) + static_cast<_Receiver&&>(__rcvr), + __mk_secondary_env_t{}(__initial, STDEXEC::get_env(__rcvr))) { __initial_opstate_.__emplace_from(STDEXEC::connect, static_cast<_CvInitialSender&&>(__initial), @@ -238,8 +259,9 @@ namespace STDEXEC } private: + using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>; using __initial_receiver_t = - __initial_receiver<_CvFinalSender, __initial_results_t, _Receiver>; + __initial_receiver<_CvFinalSender, __initial_results_t, _Receiver, __env2_t>; using __initial_opstate_t = connect_result_t<_CvInitialSender, __initial_receiver_t>; static constexpr void __cleanup_initial_opstate(__base_t* __base) noexcept @@ -251,7 +273,7 @@ namespace STDEXEC __optional<__initial_opstate_t> __initial_opstate_{}; }; - template + template struct __initial_receiver { using receiver_concept = receiver_t; @@ -281,7 +303,7 @@ namespace STDEXEC return STDEXEC::get_env(__opstate_->__rcvr_); } - __final_opstate<_CvFinalSender, _ResultType, _Receiver>* __opstate_; + __final_opstate<_CvFinalSender, _ResultType, _Receiver, _Env2>* __opstate_; }; template diff --git a/include/stdexec/__detail/__let.hpp b/include/stdexec/__detail/__let.hpp index 4db6a7d89..475b9bd13 100644 --- a/include/stdexec/__detail/__let.hpp +++ b/include/stdexec/__detail/__let.hpp @@ -64,37 +64,11 @@ namespace STDEXEC using __on_not_callable = __mbind_front_q<__callable_error_t, decltype(__let_from_set<_SetTag>)>; - // This environment is part of the receiver used to connect the secondary sender. - template - constexpr auto __mk_env2(_Attrs const & __attrs, _Env const &... __env) noexcept - { - if constexpr (__callable, - _Attrs const &, - __fwd_env_t<_Env const &>...>) - { - return __mk_sch_env(get_completion_scheduler<_SetTag>(__attrs, __fwd_env(__env)...), - __fwd_env(__env)...); - } - else if constexpr (__callable, - _Attrs const &, - __fwd_env_t<_Env const &>...>) - { - using __domain_t = __call_result_t, - _Attrs const &, - __fwd_env_t<_Env const &>...>; - return prop{get_domain, __domain_t{}}; - } - else - { - return env{}; - } - } + template + using __env2_t = __call_result_t<__mk_secondary_env_t<_SetTag>, _Sender, _Env const &...>; - template - using __env2_t = decltype(__let::__mk_env2<_SetTag>(__declval<_Attrs>(), __declval<_Env>()...)); - - template - using __result_env_t = __join_env_t<__env2_t<_SetTag, _Attrs, _Env>, _Env>; + template + using __result_env_t = __join_env_t<__env2_t<_SetTag, _Sender, _Env>, _Env>; template struct __rcvr_env @@ -209,10 +183,9 @@ namespace STDEXEC using __completions_t = __gather_completion_signatures_t< __completion_signatures_of_t<_CvSender, _Env...>, __t<_LetTag>, - __transform_signal_fn< - __t<_LetTag>, - _Fun, - __result_env_t<__t<_LetTag>, env_of_t<_CvSender>, _Env>...>::template __f, + __transform_signal_fn<__t<_LetTag>, + _Fun, + __result_env_t<__t<_LetTag>, _CvSender, _Env>...>::template __f, __cmplsigs::__default_completion, __mtry_q<__concat_completion_signatures_t>::__f>; @@ -243,7 +216,7 @@ namespace STDEXEC using __result_domain_t = __gather_completions_t< _SetTag, __completion_signatures_of_t<_Child, _Env>, - __result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>, + __result_sender_fn<_SetTag, _Fun, __result_env_t<_SetTag, _Child, _Env>>, __try_common_domain_fn<_SetTag, _Env>>; //! Metafunction creating the operation state needed to connect the result of calling @@ -278,7 +251,7 @@ namespace STDEXEC using __has_nothrow_completions_t = __gather_completions_t< completion_signatures_of_t<_Child, _Env>, _SetTag, - __has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, env_of_t<_Child>, _Env>>, + __has_nothrow_completions_fn<_Fn, __result_env_t<_SetTag, _Child, _Env>>, __qq<__mand_t>>; //! The core of the operation state for `let_*`. @@ -289,15 +262,15 @@ namespace STDEXEC using __env2_t = _Env2; using __second_rcvr_t = __rcvr_env<_Receiver, _Env2>; - template + template constexpr explicit __opstate_base(_SetTag, - _Attrs const & __attrs, - _Fun __fn, - _Receiver&& __rcvr) noexcept + _Sender const & __sndr, + _Fun __fn, + _Receiver&& __rcvr) noexcept : __rcvr_(static_cast<_Receiver&&>(__rcvr)) , __fn_(STDEXEC::__allocator_aware_forward(static_cast<_Fun&&>(__fn), __rcvr_)) // TODO(ericniebler): this needs a fallback: - , __env2_(__let::__mk_env2<_SetTag>(__attrs, STDEXEC::get_env(__rcvr_))) + , __env2_(__mk_secondary_env_t<_SetTag>()(__sndr, STDEXEC::get_env(__rcvr_))) {} constexpr virtual void __start_next() = 0; @@ -400,7 +373,7 @@ namespace STDEXEC : __opstate_base<_SetTag, _Fun, _Receiver, - __let::__env2_t<_SetTag, env_of_t<_Child>, env_of_t<_Receiver>>, + __let::__env2_t<_SetTag, _Child, env_of_t<_Receiver>>, _Tuples...> { using __env2_t = __opstate::__opstate_base::__env2_t; @@ -415,7 +388,7 @@ namespace STDEXEC noexcept(__nothrow_connectable<_Child, __first_rcvr_t> && __nothrow_move_constructible<_Fun>) : __opstate::__opstate_base(_SetTag(), - STDEXEC::get_env(__child), + __child, static_cast<_Fun&&>(__fn), static_cast<_Receiver&&>(__rcvr)) { @@ -512,16 +485,16 @@ namespace STDEXEC using __f = decltype(__impl<_Ts...>()); }; - template + template struct __domain_transform_fn { using __result_sender_fn = - __let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Attrs, _Env>...>; + __let::__result_sender_fn<_SetTag, _Fn, __result_env_t<_SetTag, _Sender, _Env>...>; template using __f = __completion_domain_of_t<_SetTag, __mcall<__result_sender_fn, _As...>, - __result_env_t<_SetTag, _Attrs, _Env>...>; + __result_env_t<_SetTag, _Sender, _Env>...>; }; //! @tparam _LetTag The tag type for the let_ operation. @@ -534,8 +507,7 @@ namespace STDEXEC { if constexpr (sender_in<_Sndr, _Env...>) { - using __domain_transform_fn = - __let::__domain_transform_fn<_SetTag, _Fn, env_of_t<_Sndr>, _Env...>; + using __domain_transform_fn = __let::__domain_transform_fn<_SetTag, _Fn, _Sndr, _Env...>; return __minvoke_or_q<__gather_completions_t, indeterminate_domain<>, __t<_LetTag>, @@ -606,7 +578,7 @@ namespace STDEXEC using __transform_fn = __result_completion_behavior_fn<__set_tag_t, _Fn, - __result_env_t<__set_tag_t, env_of_t<_Sndr>, _Env>...>; + __result_env_t<__set_tag_t, _Sndr, _Env>...>; using __completions_t = __completion_signatures_of_t<_Sndr, __fwd_env_t<_Env>...>; constexpr auto __pred_behavior = diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index 0c31f8dca..f6c85e841 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -19,10 +19,13 @@ // include these after __execution_fwd.hpp #include "__completion_signatures_of.hpp" // IWYU pragma: keep for the sender concept +#include "__concepts.hpp" #include "__config.hpp" #include "__domain.hpp" #include "__env.hpp" #include "__query.hpp" +#include "__sender_concepts.hpp" +#include "__type_traits.hpp" #include "__utility.hpp" namespace STDEXEC @@ -63,11 +66,6 @@ namespace STDEXEC static_assert(sender<__tag_invoke_result_t>); return __tag_invoke(*this, static_cast<_Scheduler &&>(__sched)); } - - static constexpr auto query(forwarding_query_t) noexcept -> bool - { - return false; - } }; inline constexpr schedule_t schedule{}; @@ -78,7 +76,7 @@ namespace STDEXEC concept scheduler = __callable // && __std::equality_comparable<__decay_t<_Scheduler>> && __std::copy_constructible<__decay_t<_Scheduler>> - && std::is_nothrow_move_constructible_v<__decay_t<_Scheduler>>; + && __nothrow_move_constructible<__decay_t<_Scheduler>>; template using schedule_result_t = __call_result_t; @@ -381,14 +379,19 @@ namespace STDEXEC }; template - STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE - __sched_attrs(_Scheduler) -> __sched_attrs>; + STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE __sched_attrs(_Scheduler) -> __sched_attrs<_Scheduler>; ////////////////////////////////////////////////////////////////////////////// // See SCHED-ENV from [exec.snd.expos] - template + template struct __sched_env { + using __domain_t = __minvoke_or_q<__detail::__scheduler_domain_t, void, _Scheduler, _Env...>; + + constexpr explicit __sched_env(_Scheduler __sch, _Env const &...) noexcept + : __sched_{std::move(__sch)} + { } + STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) constexpr auto query(get_scheduler_t) const noexcept { @@ -396,7 +399,8 @@ namespace STDEXEC } STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) - constexpr auto query(get_domain_t) const noexcept -> __detail::__scheduler_domain_t<_Scheduler> + constexpr auto query(get_domain_t) const noexcept -> __domain_t + requires __not_same_as<__domain_t, void> { return {}; } @@ -404,31 +408,96 @@ namespace STDEXEC _Scheduler __sched_; }; - template + template STDEXEC_HOST_DEVICE_DEDUCTION_GUIDE - __sched_env(_Scheduler) -> __sched_env>; + __sched_env(_Scheduler, _Env const &...) -> __sched_env<_Scheduler, _Env...>; + + template + constexpr auto __mk_sch_env(_Sch __sch) noexcept + { + return __sched_env{std::move(__sch)}; + } - struct __mk_sch_env_t + template + constexpr auto __mk_sch_env([[maybe_unused]] _Sch __sch, _Env const &__env) noexcept { - template - constexpr auto operator()([[maybe_unused]] _Sch __sch, _Env const &...__env) const noexcept + if constexpr (__completes_inline>, _Env> + && __callable) { - if constexpr (__completes_inline>, _Env...> - && (__callable || ...)) - { - return (__sched_env{get_completion_scheduler(get_scheduler(__env), - __hide_scheduler{__env})}, - ...); - } - else + auto __sch2 = get_completion_scheduler(get_scheduler(__env), + __hide_scheduler{__env}); + return __sched_env{std::move(__sch2), __env}; + } + else + { + return __sched_env{std::move(__sch)}; + } + } + + namespace __detail + { + template + struct __mk_secondary_env_impl + { + template + constexpr auto operator()(_Sender const &__sndr, _Env const &__env) const noexcept { - return __sched_env{__sch}; + using __env_t = __fwd_env_t<_Env const &>; + using __attrs_t = env_of_t<_Sender const &>; + using __domain_t = __make_domain_t<__completion_domain_of_t<_SetTags, _Sender, _Env>...>; + // We can only know the scheduler that the secondary sender is started on if there + // is exactly one kind of completion that starts the secondary sender. + constexpr bool __has_completion_scheduler = + sizeof...(_SetTags) == 1 + && (__callable, __attrs_t, __env_t> || ...); + + if constexpr (__has_completion_scheduler) + { + auto __sch = (get_completion_scheduler<_SetTags>(get_env(__sndr), __fwd_env(__env)), ...); + return STDEXEC::__mk_sch_env(__sch, __fwd_env(__env)); + } + else if constexpr (__not_same_as<__domain_t, indeterminate_domain<>>) + { + return __env::cprop(); + } + else + { + return env{}; + } } + }; + } // namespace __detail + + //! This environment is for when one sender is started from the completion of another + //! sender. In that case, the completion scheduler/domain for the first sender should + //! be used as the scheduler/domain for the second sender. + //! + //! This environment is used by the \c let_[value|error|stopped] algorithms as well as + //! the \c finally algorithm. + //! + //! \note This env assumes that the results of the first sender are decay-copied into + //! the operation state of the composite sender. + //! + //! \tparam _PrimarySender The sender whose completion is starting the next sender. + //! \tparam _Env The environment of the receiver connected to the primary sender. + //! \tparam _SetTags The completions that cause the next sender to start. For example, + //! for \c let_value, this would be \c set_value_t, and for \c finally, this would be + //! \c set_value_t, \c set_error_t, and \c set_stopped_t. + template + struct __mk_secondary_env_t + { + template + constexpr auto operator()(_PrimarySender const &__sndr, _Env const &__env) const noexcept + { + using namespace __detail; + using __env_t = __fwd_env_t<_Env const &>; + using __never_sends_fn = __mbind_back_q<__never_sends_t, _PrimarySender, __env_t>; + using __remove_if_fn = __mremove_if<__never_sends_fn, __qq<__mk_secondary_env_impl>>; + using __impl_t = __minvoke<__remove_if_fn, _SetTags...>; + return __impl_t{}(__sndr, __env); } }; - inline constexpr __mk_sch_env_t __mk_sch_env{}; - ////////////////////////////////////////////////////////////////////////////////////////// // __infallible_scheduler template diff --git a/include/stdexec/__detail/__sender_concepts.hpp b/include/stdexec/__detail/__sender_concepts.hpp index 8d5c775f7..2ae837442 100644 --- a/include/stdexec/__detail/__sender_concepts.hpp +++ b/include/stdexec/__detail/__sender_concepts.hpp @@ -100,6 +100,9 @@ namespace STDEXEC concept __never_sends = sender_in<_Sender, _Env...> // && __count_of<_Tag, _Sender, _Env...>::value == 0; + template + using __never_sends_t = __mbool<__never_sends<_Tag, _Sender, _Env...>>; + template concept __single_value_sender = sender_in<_Sender, _Env...> // && requires { typename __single_sender_value_t<_Sender, _Env...>; }; diff --git a/include/stdexec/__detail/__starts_on.hpp b/include/stdexec/__detail/__starts_on.hpp index 4e31ddf69..f482cf8c9 100644 --- a/include/stdexec/__detail/__starts_on.hpp +++ b/include/stdexec/__detail/__starts_on.hpp @@ -69,7 +69,7 @@ namespace STDEXEC template static constexpr auto __mk_env2(_Scheduler __sch, _Env&&... __env) { - return env(__mk_sch_env(__sch, __env...), static_cast<_Env&&>(__env)...); + return env(STDEXEC::__mk_sch_env(__sch, __env...), static_cast<_Env&&>(__env)...); } template diff --git a/include/stdexec/__detail/__transfer_just.hpp b/include/stdexec/__detail/__transfer_just.hpp index ab2837120..b8c199a7b 100644 --- a/include/stdexec/__detail/__transfer_just.hpp +++ b/include/stdexec/__detail/__transfer_just.hpp @@ -82,7 +82,7 @@ namespace STDEXEC constexpr auto operator()(_Scheduler const & __sched, auto const &...) const noexcept { static_assert(scheduler<_Scheduler>, "transfer_just requires a scheduler"); - return __sched_attrs{std::cref(__sched)}; + return __sched_attrs{__sched}; } }; diff --git a/include/stdexec/__detail/__when_all.hpp b/include/stdexec/__detail/__when_all.hpp index 699bd0a71..9d5dfd41c 100644 --- a/include/stdexec/__detail/__when_all.hpp +++ b/include/stdexec/__detail/__when_all.hpp @@ -583,7 +583,7 @@ namespace STDEXEC _Child const &...) noexcept { // TODO(ericniebler): check this use of __sched_attrs - return __sched_attrs{std::cref(__sched)}; + return __sched_attrs{__sched}; }; template @@ -602,7 +602,7 @@ namespace STDEXEC _Scheduler const & __sched, _Child const &...) noexcept { - return __sched_attrs{std::cref(__sched)}; + return __sched_attrs{__sched}; }; template From d78265617fb3535386cce3877d44ed08bca48206 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 2 Mar 2026 14:17:30 -0800 Subject: [PATCH 3/3] fixes --- include/stdexec/__detail/__finally.hpp | 9 +++------ include/stdexec/__detail/__schedulers.hpp | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/include/stdexec/__detail/__finally.hpp b/include/stdexec/__detail/__finally.hpp index e67cc10a7..394db417f 100644 --- a/include/stdexec/__detail/__finally.hpp +++ b/include/stdexec/__detail/__finally.hpp @@ -102,7 +102,7 @@ namespace STDEXEC template struct __opstate_base { - _Receiver __rcvr_{}; + _Receiver __rcvr_{}; STDEXEC_ATTRIBUTE(no_unique_address) _Env2 const __env2_{}; _ResultType __result_{__no_init}; // __variant<__tuple, ...> @@ -234,10 +234,8 @@ namespace STDEXEC _Receiver, __env2_t<_CvInitialSender, _Receiver>> { - using __base_t = __final_opstate_t<_CvInitialSender, - _CvFinalSender, - _Receiver, - __env2_t<_CvInitialSender, _Receiver>>; + using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>; + using __base_t = __final_opstate_t<_CvInitialSender, _CvFinalSender, _Receiver, __env2_t>; using __initial_results_t = __base_t::__results_t; constexpr explicit __opstate(_CvInitialSender&& __initial, @@ -259,7 +257,6 @@ namespace STDEXEC } private: - using __env2_t = __final::__env2_t<_CvInitialSender, _Receiver>; using __initial_receiver_t = __initial_receiver<_CvFinalSender, __initial_results_t, _Receiver, __env2_t>; using __initial_opstate_t = connect_result_t<_CvInitialSender, __initial_receiver_t>; diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index f6c85e841..bb7266c07 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -390,7 +390,7 @@ namespace STDEXEC constexpr explicit __sched_env(_Scheduler __sch, _Env const &...) noexcept : __sched_{std::move(__sch)} - { } + {} STDEXEC_ATTRIBUTE(nodiscard, always_inline, host, device) constexpr auto query(get_scheduler_t) const noexcept