stdexec: update to latest commit

Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I8c34e20a8757c6d84a6151cfb9a5a9fd5b13c75a
diff --git a/include/sdbusplus/async/stdexec/__detail/__config.hpp b/include/sdbusplus/async/stdexec/__detail/__config.hpp
index 08e11ac..8772163 100644
--- a/include/sdbusplus/async/stdexec/__detail/__config.hpp
+++ b/include/sdbusplus/async/stdexec/__detail/__config.hpp
@@ -85,6 +85,27 @@
 #define STDEXEC_HAS_BUILTIN(...) 0
 #endif
 
+#if STDEXEC_HAS_BUILTIN(__is_trivially_copyable) || STDEXEC_MSVC()
+#define STDEXEC_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
+#else
+#define STDEXEC_IS_TRIVIALLY_COPYABLE(...)                                     \
+    std::is_trivially_copyable_v<__VA_ARGS__>
+#endif
+
+#if STDEXEC_HAS_BUILTIN(__is_base_of) || STDEXEC_MSVC()
+#define STDEXEC_IS_BASE_OF(...) __is_base_of(__VA_ARGS__)
+#else
+#define STDEXEC_IS_BASE_OF(...) std::is_base_of_v<__VA_ARGS__>
+#endif
+
+#if STDEXEC_HAS_BUILTIN(__is_convertible_to) || STDEXEC_MSVC()
+#define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible_to(__VA_ARGS__)
+#elif STDEXEC_HAS_BUILTIN(__is_convertible)
+#define STDEXEC_IS_CONVERTIBLE_TO(...) __is_convertible(__VA_ARGS__)
+#else
+#define STDEXEC_IS_CONVERTIBLE_TO(...) std::is_convertible_v<__VA_ARGS__>
+#endif
+
 // Before gcc-12, gcc really didn't like tuples or variants of immovable types
 #if STDEXEC_GCC() && (__GNUC__ < 12)
 #define STDEXEC_IMMOVABLE(_XP) _XP(_XP&&)
diff --git a/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp b/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
index 260cdc7..93e303a 100644
--- a/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
+++ b/include/sdbusplus/async/stdexec/__detail/__type_traits.hpp
@@ -27,7 +27,7 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////////////
 // __decay_t: An efficient implementation for std::decay
-#if __has_builtin(__decay)
+#if STDEXEC_HAS_BUILTIN(__decay)
 
 template <class _Ty>
 using __decay_t = __decay(_Ty);
diff --git a/include/sdbusplus/async/stdexec/any_sender_of.hpp b/include/sdbusplus/async/stdexec/any_sender_of.hpp
index ac7541b..fdadae7 100644
--- a/include/sdbusplus/async/stdexec/any_sender_of.hpp
+++ b/include/sdbusplus/async/stdexec/any_sender_of.hpp
@@ -295,14 +295,163 @@
     class __t;
 };
 
+template <class _Vtable, class _Allocator,
+          std::size_t _Alignment = alignof(std::max_align_t),
+          std::size_t _InlineSize = 3 * sizeof(void*)>
+struct __immovable_storage
+{
+    class __t : __immovable
+    {
+        static constexpr std::size_t __buffer_size = std::max(_InlineSize,
+                                                              sizeof(void*));
+        static constexpr std::size_t __alignment = std::max(_Alignment,
+                                                            alignof(void*));
+        using __with_delete = __delete_t(void() noexcept);
+        using __vtable_t = __storage_vtable<_Vtable, __with_delete>;
+
+        template <class _Tp>
+        static constexpr bool __is_small = sizeof(_Tp) <= __buffer_size &&
+                                           alignof(_Tp) <= __alignment;
+
+        template <class _Tp>
+        static constexpr const __vtable_t* __get_vtable_of_type() noexcept
+        {
+            return &__storage_vtbl<__t, __decay_t<_Tp>, _Vtable, __with_delete>;
+        }
+
+      public:
+        using __id = __immovable_storage;
+
+        __t() = default;
+
+        template <__not_decays_to<__t> _Tp>
+            requires __callable<__create_vtable_t, __mtype<_Vtable>,
+                                __mtype<__decay_t<_Tp>>>
+        __t(_Tp&& __object) : __vtable_{__get_vtable_of_type<_Tp>()}
+        {
+            using _Dp = __decay_t<_Tp>;
+            if constexpr (__is_small<_Dp>)
+            {
+                __construct_small<_Dp>((_Tp&&)__object);
+            }
+            else
+            {
+                __construct_large<_Dp>((_Tp&&)__object);
+            }
+        }
+
+        template <class _Tp, class... _Args>
+            requires __callable<__create_vtable_t, __mtype<_Vtable>,
+                                __mtype<_Tp>>
+        __t(std::in_place_type_t<_Tp>, _Args&&... __args) :
+            __vtable_{__get_vtable_of_type<_Tp>()}
+        {
+            if constexpr (__is_small<_Tp>)
+            {
+                __construct_small<_Tp>((_Args&&)__args...);
+            }
+            else
+            {
+                __construct_large<_Tp>((_Args&&)__args...);
+            }
+        }
+
+        ~__t()
+        {
+            __reset();
+        }
+
+        void __reset() noexcept
+        {
+            (*__vtable_)(__delete, this);
+            __object_pointer_ = nullptr;
+            __vtable_ = __default_storage_vtable((__vtable_t*)nullptr);
+        }
+
+        const _Vtable* __get_vtable() const noexcept
+        {
+            return __vtable_;
+        }
+
+        void* __get_object_pointer() const noexcept
+        {
+            return __object_pointer_;
+        }
+
+      private:
+        template <class _Tp, class... _As>
+        void __construct_small(_As&&... __args)
+        {
+            static_assert(sizeof(_Tp) <= __buffer_size &&
+                          alignof(_Tp) <= __alignment);
+            _Tp* __pointer =
+                static_cast<_Tp*>(static_cast<void*>(&__buffer_[0]));
+            using _Alloc = typename std::allocator_traits<
+                _Allocator>::template rebind_alloc<_Tp>;
+            _Alloc __alloc{__allocator_};
+            std::allocator_traits<_Alloc>::construct(__alloc, __pointer,
+                                                     (_As&&)__args...);
+            __object_pointer_ = __pointer;
+        }
+
+        template <class _Tp, class... _As>
+        void __construct_large(_As&&... __args)
+        {
+            using _Alloc = typename std::allocator_traits<
+                _Allocator>::template rebind_alloc<_Tp>;
+            _Alloc __alloc{__allocator_};
+            _Tp* __pointer = std::allocator_traits<_Alloc>::allocate(__alloc,
+                                                                     1);
+            try
+            {
+                std::allocator_traits<_Alloc>::construct(__alloc, __pointer,
+                                                         (_As&&)__args...);
+            }
+            catch (...)
+            {
+                std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer,
+                                                          1);
+                throw;
+            }
+            __object_pointer_ = __pointer;
+        }
+
+        template <class _Tp>
+        friend void tag_invoke(__delete_t, __mtype<_Tp>, __t& __self) noexcept
+        {
+            if (!__self.__object_pointer_)
+            {
+                return;
+            }
+            using _Alloc = typename std::allocator_traits<
+                _Allocator>::template rebind_alloc<_Tp>;
+            _Alloc __alloc{__self.__allocator_};
+            _Tp* __pointer = static_cast<_Tp*>(
+                std::exchange(__self.__object_pointer_, nullptr));
+            std::allocator_traits<_Alloc>::destroy(__alloc, __pointer);
+            if constexpr (!__is_small<_Tp>)
+            {
+                std::allocator_traits<_Alloc>::deallocate(__alloc, __pointer,
+                                                          1);
+            }
+        }
+
+      private:
+        const __vtable_t* __vtable_{
+            __default_storage_vtable((__vtable_t*)nullptr)};
+        void* __object_pointer_{nullptr};
+        alignas(__alignment) std::byte __buffer_[__buffer_size]{};
+        STDEXEC_NO_UNIQUE_ADDRESS _Allocator __allocator_{};
+    };
+};
+
 template <class _Vtable, class _Allocator, bool _Copyable,
           std::size_t _Alignment, std::size_t _InlineSize>
 class __storage<_Vtable, _Allocator, _Copyable, _Alignment, _InlineSize>::__t :
     __if_c<_Copyable, __, __move_only>
 {
-    static_assert(
-        std::is_convertible_v<
-            typename std::allocator_traits<_Allocator>::void_pointer, void*>);
+    static_assert(STDEXEC_IS_CONVERTIBLE_TO(
+        typename std::allocator_traits<_Allocator>::void_pointer, void*));
 
     static constexpr std::size_t __buffer_size = std::max(_InlineSize,
                                                           sizeof(void*));
@@ -529,12 +678,47 @@
     STDEXEC_NO_UNIQUE_ADDRESS _Allocator __allocator_{};
 };
 
+struct __empty_vtable
+{
+    template <class _Sender>
+    friend const __empty_vtable* tag_invoke(__create_vtable_t,
+                                            __mtype<__empty_vtable>,
+                                            __mtype<_Sender>) noexcept
+    {
+        static const __empty_vtable __vtable_{};
+        return &__vtable_;
+    }
+};
+
+template <class _VTable = __empty_vtable,
+          class _Allocator = std::allocator<std::byte>>
+using __immovable_storage_t = __t<__immovable_storage<_VTable, _Allocator>>;
+
 template <class _VTable, class _Allocator = std::allocator<std::byte>>
 using __unique_storage_t = __t<__storage<_VTable, _Allocator>>;
 
 template <class _VTable, class _Allocator = std::allocator<std::byte>>
 using __copyable_storage_t = __t<__storage<_VTable, _Allocator, true>>;
 
+template <class _Tag, class... _As>
+_Tag __tag_type(_Tag (*)(_As...));
+
+template <class _Tag, class... _As>
+_Tag __tag_type(_Tag (*)(_As...) noexcept);
+
+template <class _Query>
+concept __is_stop_token_query = requires {
+                                    {
+                                        __tag_type(static_cast<_Query>(nullptr))
+                                    } -> same_as<get_stop_token_t>;
+                                };
+
+template <class _Query>
+concept __is_not_stop_token_query = !__is_stop_token_query<_Query>;
+
+template <class _Query>
+using __is_not_stop_token_query_v = __mbool<__is_not_stop_token_query<_Query>>;
+
 namespace __rec
 {
 template <class _Sig>
@@ -592,11 +776,87 @@
 };
 
 template <class... _Sigs, class... _Queries>
+    requires(__is_not_stop_token_query<_Queries> && ...)
 struct __ref<completion_signatures<_Sigs...>, _Queries...>
 {
   private:
     using __vtable_t =
-        __t<__vtable<completion_signatures<_Sigs...>, _Queries...>>;
+        stdexec::__t<__vtable<completion_signatures<_Sigs...>, _Queries...>>;
+
+    struct __env_t
+    {
+        const __vtable_t* __vtable_;
+        void* __rcvr_;
+        in_place_stop_token __token_;
+
+        template <class _Tag, class... _As>
+            requires __callable<const __vtable_t&, _Tag, void*, _As...>
+        friend auto
+            tag_invoke(_Tag, const __env_t& __self, _As&&... __as) noexcept(
+                __nothrow_callable<const __vtable_t&, _Tag, void*, _As...>)
+                -> __call_result_t<const __vtable_t&, _Tag, void*, _As...>
+        {
+            return (*__self.__vtable_)(_Tag{}, __self.__rcvr_, (_As&&)__as...);
+        }
+
+        friend in_place_stop_token tag_invoke(get_stop_token_t,
+                                              const __env_t& __self) noexcept
+        {
+            return __self.__token_;
+        }
+    } __env_;
+
+  public:
+    using is_receiver = void;
+    using __id = __ref;
+    using __t = __ref;
+
+    template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr>
+        requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> &&
+                 (__callable<__query_vfun_fn<_Rcvr>, _Queries> && ...)
+    __ref(_Rcvr& __rcvr) noexcept :
+        __env_{__create_vtable(__mtype<__vtable_t>{}, __mtype<_Rcvr>{}),
+               &__rcvr, stdexec::get_stop_token(stdexec::get_env(__rcvr))}
+    {}
+
+    template <__completion_tag _Tag, __decays_to<__ref> _Self, class... _As>
+        requires __one_of<_Tag(_As...), _Sigs...>
+    friend void tag_invoke(_Tag, _Self&& __self, _As&&... __as) noexcept
+    {
+        (*static_cast<const __rcvr_vfun<_Tag(_As...)>*>(__self.__env_.__vtable_)
+              ->__fn_)(((_Self&&)__self).__env_.__rcvr_, (_As&&)__as...);
+    }
+
+    template <std::same_as<__ref> Self>
+    friend const __env_t& tag_invoke(get_env_t, const Self& __self) noexcept
+    {
+        return __self.__env_;
+    }
+};
+
+__mbool<true> __test_never_stop_token(
+    get_stop_token_t (*)(never_stop_token (*)() noexcept));
+
+template <class _Tag, class _Ret, class... _As>
+__mbool<false> __test_never_stop_token(_Tag (*)(_Ret (*)(_As...) noexcept));
+
+template <class _Tag, class _Ret, class... _As>
+__mbool<false> __test_never_stop_token(_Tag (*)(_Ret (*)(_As...)));
+
+template <class _Query>
+using __is_never_stop_token_query =
+    decltype(__test_never_stop_token(static_cast<_Query>(nullptr)));
+
+template <class... _Sigs, class... _Queries>
+    requires(__is_stop_token_query<_Queries> || ...)
+struct __ref<completion_signatures<_Sigs...>, _Queries...>
+{
+  private:
+    using _FilteredQueries =
+        __minvoke<__remove_if<__q<__is_never_stop_token_query>>, _Queries...>;
+    using __vtable_t = stdexec::__t<
+        __mapply<__mbind_front_q<__vtable, completion_signatures<_Sigs...>>,
+                 _FilteredQueries>>;
 
     struct __env_t
     {
@@ -616,6 +876,8 @@
 
   public:
     using is_receiver = void;
+    using __id = __ref;
+    using __t = __ref;
 
     template <__none_of<__ref, const __ref, __env_t, const __env_t> _Rcvr>
         requires receiver_of<_Rcvr, completion_signatures<_Sigs...>> &&
@@ -663,59 +925,141 @@
     }
 };
 
-using __unique_operation_storage = __unique_storage_t<__operation_vtable>;
+using __immovable_operation_storage = __immovable_storage_t<__operation_vtable>;
 
 template <class _Sigs, class _Queries>
 using __receiver_ref =
     __mapply<__mbind_front<__q<__rec::__ref>, _Sigs>, _Queries>;
 
-template <class _Receiver, class _Sigs, class _Queries>
-struct __operation_base
+struct __on_stop_t
 {
-    STDEXEC_NO_UNIQUE_ADDRESS _Receiver __receiver_;
+    stdexec::in_place_stop_source& __source_;
+
+    void operator()() const noexcept
+    {
+        __source_.request_stop();
+    }
 };
 
-template <class _Sender, class _Receiver, class _Queries>
-struct __operation
+template <class _Receiver>
+struct __operation_base
 {
-    using _Sigs = completion_signatures_of_t<_Sender>;
-    using __receiver_ref_t = __receiver_ref<_Sigs, _Queries>;
+    STDEXEC_NO_UNIQUE_ADDRESS _Receiver __rcvr_;
+    stdexec::in_place_stop_source __stop_source_{};
+    using __stop_callback = typename stdexec::stop_token_of_t<
+        stdexec::env_of_t<_Receiver>>::template callback_type<__on_stop_t>;
+    std::optional<__stop_callback> __on_stop_{};
+};
 
-    struct __rec
+template <class _Env>
+using __env_t =
+    __make_env_t<_Env, __with<get_stop_token_t, in_place_stop_token>>;
+
+template <class _ReceiverId>
+struct __stoppable_receiver
+{
+    using _Receiver = stdexec::__t<_ReceiverId>;
+
+    struct __t
     {
-        using is_receiver = void;
-        __operation_base<_Receiver, _Sigs, _Queries>* __op_;
+        __operation_base<_Receiver>* __op_;
 
-        template <__completion_tag _CPO, __decays_to<__rec> _Self,
+        template <same_as<set_value_t> _SetValue, same_as<__t> _Self,
                   class... _Args>
-            requires __callable<_CPO, _Receiver&&, _Args...>
-        friend void tag_invoke(_CPO, _Self&& __self, _Args&&... __args) noexcept
+            requires __callable<_SetValue, _Receiver&&, _Args...>
+        friend void tag_invoke(_SetValue, _Self&& __self,
+                               _Args&&... __args) noexcept
         {
-            _CPO{}((_Receiver&&)__self.__op_->__receiver_, (_Args&&)__args...);
+            __self.__op_->__on_stop_.reset();
+            _SetValue{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_),
+                        static_cast<_Args&&>(__args)...);
         }
 
-        friend env_of_t<_Receiver> tag_invoke(get_env_t,
-                                              const __rec& __self) noexcept
+        template <same_as<set_error_t> _SetError, same_as<__t> _Self,
+                  class _Error>
+            requires __callable<_SetError, _Receiver&&, _Error>
+        friend void tag_invoke(_SetError, _Self&& __self,
+                               _Error&& __err) noexcept
         {
-            return get_env(__self.__op_->__receiver_);
+            __self.__op_->__on_stop_.reset();
+            _SetError{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_),
+                        static_cast<_Error&&>(__err));
+        }
+
+        template <same_as<set_stopped_t> _SetStopped, same_as<__t> _Self>
+            requires __callable<_SetStopped, _Receiver&&>
+        friend void tag_invoke(_SetStopped, _Self&& __self) noexcept
+        {
+            __self.__op_->__on_stop_.reset();
+            _SetStopped{}(static_cast<_Receiver&&>(__self.__op_->__rcvr_));
+        }
+
+        template <same_as<get_env_t> _GetEnv, same_as<__t> _Self>
+        friend __env_t<env_of_t<_Receiver>>
+            tag_invoke(_GetEnv, const _Self& __self) noexcept
+        {
+            return __make_env(
+                get_env(__self.__op_->__rcvr_),
+                __with_(get_stop_token,
+                        __self.__op_->__stop_source_.get_token()));
         }
     };
+};
 
-    class __t : __immovable, __operation_base<_Receiver, _Sigs, _Queries>
+template <class _ReceiverId>
+using __stoppable_receiver_t = stdexec::__t<__stoppable_receiver<_ReceiverId>>;
+
+template <class _ReceiverId, bool>
+struct __operation
+{
+    using _Receiver = stdexec::__t<_ReceiverId>;
+
+    class __t : public __operation_base<_Receiver>
     {
       public:
         using __id = __operation;
 
+        template <class _Sender>
         __t(_Sender&& __sender, _Receiver&& __receiver) :
-            __operation_base<_Receiver, _Sigs, _Queries>{
-                (_Receiver&&)__receiver},
-            __storage_{__sender.__connect(__receiver_ref_t{__rec_})}
+            __operation_base<_Receiver>{static_cast<_Receiver&&>(__receiver)},
+            __rec_{this}, __storage_{__sender.__connect(__rec_)}
         {}
 
       private:
-        __rec __rec_{
-            static_cast<__operation_base<_Receiver, _Sigs, _Queries>*>(this)};
-        __unique_operation_storage __storage_{};
+        __stoppable_receiver_t<_ReceiverId> __rec_;
+        __immovable_operation_storage __storage_{};
+
+        friend void tag_invoke(start_t, __t& __self) noexcept
+        {
+            __self.__on_stop_.emplace(
+                stdexec::get_stop_token(stdexec::get_env(__self.__rcvr_)),
+                __on_stop_t{__self.__stop_source_});
+            STDEXEC_ASSERT(__self.__storage_.__get_vtable()->__start_);
+            __self.__storage_.__get_vtable()->__start_(
+                __self.__storage_.__get_object_pointer());
+        }
+    };
+};
+
+template <class _ReceiverId>
+struct __operation<_ReceiverId, false>
+{
+    using _Receiver = stdexec::__t<_ReceiverId>;
+
+    class __t
+    {
+      public:
+        using __id = __operation;
+
+        template <class _Sender>
+        __t(_Sender&& __sender, _Receiver&& __receiver) :
+            __rec_{static_cast<_Receiver&&>(__receiver)},
+            __storage_{__sender.__connect(__rec_)}
+        {}
+
+      private:
+        STDEXEC_NO_UNIQUE_ADDRESS _Receiver __rec_;
+        __immovable_operation_storage __storage_{};
 
         friend void tag_invoke(start_t, __t& __self) noexcept
         {
@@ -753,6 +1097,9 @@
 struct __sender
 {
     using __receiver_ref_t = __receiver_ref<_Sigs, _ReceiverQueries>;
+    static constexpr bool __with_in_place_stop_token =
+        __v<__mapply<__mall_of<__q<__is_not_stop_token_query_v>>,
+                     _ReceiverQueries>>;
 
     class __vtable : public __query_vtable<_SenderQueries>
     {
@@ -764,7 +1111,7 @@
             return *this;
         }
 
-        __unique_operation_storage (*__connect_)(void*, __receiver_ref_t);
+        __immovable_operation_storage (*__connect_)(void*, __receiver_ref_t);
 
       private:
         template <sender_to<__receiver_ref_t> _Sender>
@@ -774,16 +1121,17 @@
             static const __vtable __vtable_{
                 {*__create_vtable(__mtype<__query_vtable<_SenderQueries>>{},
                                   __mtype<_Sender>{})},
-                [](void* __object_pointer,
-                   __receiver_ref_t __receiver) -> __unique_operation_storage {
+                [](void* __object_pointer, __receiver_ref_t __receiver)
+                    -> __immovable_operation_storage {
                     _Sender& __sender =
                         *static_cast<_Sender*>(__object_pointer);
                     using __op_state_t =
                         connect_result_t<_Sender, __receiver_ref_t>;
-                    return __unique_operation_storage{
+                    return __immovable_operation_storage{
                         std::in_place_type<__op_state_t>, __conv{[&] {
-                            return connect((_Sender&&)__sender,
-                                           (__receiver_ref_t&&)__receiver);
+                            return stdexec::connect(
+                                (_Sender&&)__sender,
+                                (__receiver_ref_t&&)__receiver);
                         }}};
                 }};
             return &__vtable_;
@@ -834,7 +1182,7 @@
         __t(_Sender&& __sndr) : __storage_{(_Sender&&)__sndr}
         {}
 
-        __unique_operation_storage __connect(__receiver_ref_t __receiver)
+        __immovable_operation_storage __connect(__receiver_ref_t __receiver)
         {
             return __storage_.__get_vtable()->__connect_(
                 __storage_.__get_object_pointer(),
@@ -850,8 +1198,8 @@
         __unique_storage_t<__vtable> __storage_;
 
         template <receiver_of<_Sigs> _Rcvr>
-        friend stdexec::__t<
-            __operation<__t, __decay_t<_Rcvr>, _ReceiverQueries>>
+        friend stdexec::__t<__operation<stdexec::__id<__decay_t<_Rcvr>>,
+                                        __with_in_place_stop_token>>
             tag_invoke(connect_t, __t&& __self, _Rcvr&& __rcvr)
         {
             return {(__t&&)__self, (_Rcvr&&)__rcvr};
@@ -903,8 +1251,8 @@
                     return __sender_t{schedule(__scheduler)};
                 },
                 [](const void* __self, const void* __other) noexcept -> bool {
-                    static_assert(noexcept(std::declval<const _Scheduler&>() ==
-                                           std::declval<const _Scheduler&>()));
+                    static_assert(noexcept(__declval<const _Scheduler&>() ==
+                                           __declval<const _Scheduler&>()));
                     STDEXEC_ASSERT(__self && __other);
                     const _Scheduler& __self_scheduler =
                         *static_cast<const _Scheduler*>(__self);
@@ -1026,9 +1374,8 @@
         using completion_signatures =
             typename __sender_base::completion_signatures;
 
-        template <class _Sender>
-            requires(!stdexec::__decays_to<_Sender, any_sender>) &&
-                    stdexec::sender<_Sender>
+        template <stdexec::__not_decays_to<any_sender> _Sender>
+            requires stdexec::sender_to<_Sender, __receiver_base>
         any_sender(_Sender&& __sender) noexcept(
             stdexec::__nothrow_constructible_from<__sender_base, _Sender>) :
             __sender_((_Sender&&)__sender)
diff --git a/include/sdbusplus/async/stdexec/async_scope.hpp b/include/sdbusplus/async/stdexec/async_scope.hpp
index 1f84717..12a19db 100644
--- a/include/sdbusplus/async/stdexec/async_scope.hpp
+++ b/include/sdbusplus/async/stdexec/async_scope.hpp
@@ -74,7 +74,7 @@
     explicit __when_empty_op(const __impl* __scope, _Constrained&& __sndr,
                              _Receiver __rcvr) :
         __task{{}, __scope, __notify_waiter},
-        __op_(connect((_Constrained&&)__sndr, (_Receiver&&)__rcvr))
+        __op_(stdexec::connect((_Constrained&&)__sndr, (_Receiver&&)__rcvr))
     {}
 
   private:
@@ -156,6 +156,7 @@
 template <class _ReceiverId>
 struct __nest_rcvr
 {
+    using is_receiver = void;
     using _Receiver = __t<_ReceiverId>;
     __nest_op_base<_ReceiverId>* __op_;
 
@@ -210,7 +211,7 @@
     template <__decays_to<_Constrained> _Sender, __decays_to<_Receiver> _Rcvr>
     explicit __nest_op(const __impl* __scope, _Sender&& __c, _Rcvr&& __rcvr) :
         __nest_op_base<_ReceiverId>{{}, __scope, (_Rcvr&&)__rcvr},
-        __op_(connect((_Sender&&)__c, __nest_rcvr<_ReceiverId>{this}))
+        __op_(stdexec::connect((_Sender&&)__c, __nest_rcvr<_ReceiverId>{this}))
     {}
 
   private:
@@ -549,6 +550,7 @@
 template <class _CompletionsId, class _EnvId>
 struct __future_rcvr
 {
+    using is_receiver = void;
     using _Completions = __t<_CompletionsId>;
     using _Env = __t<_EnvId>;
     __future_state_base<_Completions, _Env>* __state_;
@@ -617,8 +619,9 @@
 
     __future_state(_Sender __sndr, _Env __env, const __impl* __scope) :
         __future_state_base<_Completions, _Env>((_Env&&)__env, __scope),
-        __op_(connect((_Sender&&)__sndr,
-                      __future_receiver_t<_Sender, _Env>{this, __scope}))
+        __op_(
+            stdexec::connect((_Sender&&)__sndr,
+                             __future_receiver_t<_Sender, _Env>{this, __scope}))
     {}
 
     connect_result_t<_Sender, __future_receiver_t<_Sender, _Env>> __op_;
@@ -707,6 +710,7 @@
 template <class _EnvId>
 struct __spawn_rcvr
 {
+    using is_receiver = void;
     using _Env = __t<_EnvId>;
     __spawn_op_base<_EnvId>* __op_;
     const __impl* __scope_;
@@ -749,7 +753,8 @@
             [](__spawn_op_base<_EnvId>* __op) {
         delete static_cast<__spawn_op*>(__op);
             }},
-    __op_(connect((_Sndr&&)__sndr, __spawn_receiver_t<_Env>{this, __scope}))
+    __op_(stdexec::connect((_Sndr&&)__sndr,
+                           __spawn_receiver_t<_Env>{this, __scope}))
     {}
 
     void __start_() noexcept
diff --git a/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp b/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
index c32f3af..dc6df2e 100644
--- a/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
+++ b/include/sdbusplus/async/stdexec/at_coroutine_exit.hpp
@@ -44,6 +44,7 @@
     {
         struct __t
         {
+            using is_receiver = void;
             using __id = __receiver_id;
             _Receiver __receiver_;
 
@@ -92,8 +93,9 @@
             friend connect_result_t<_Sender, __receiver<_Receiver>>
                 tag_invoke(connect_t, __t&& __self, _Receiver&& __rcvr) noexcept
             {
-                return connect((_Sender&&)__self.__sender_,
-                               __receiver<_Receiver>{(_Receiver&&)__rcvr});
+                return stdexec::connect(
+                    (_Sender&&)__self.__sender_,
+                    __receiver<_Receiver>{(_Receiver&&)__rcvr});
             }
 
             template <__decays_to<__t> _Self, class _Env>
diff --git a/include/sdbusplus/async/stdexec/commit.info b/include/sdbusplus/async/stdexec/commit.info
index 6031367..6c3c5cd 100644
--- a/include/sdbusplus/async/stdexec/commit.info
+++ b/include/sdbusplus/async/stdexec/commit.info
@@ -1 +1 @@
-b790506e622afd3c945b2319d254cbfa301c0c9e
+f1409100e46d3bdf2cbf2d6fb6c8e4a96e8bd307
diff --git a/include/sdbusplus/async/stdexec/concepts.hpp b/include/sdbusplus/async/stdexec/concepts.hpp
index b64a95a..3098123 100644
--- a/include/sdbusplus/async/stdexec/concepts.hpp
+++ b/include/sdbusplus/async/stdexec/concepts.hpp
@@ -56,13 +56,13 @@
 concept integral = std::is_integral_v<T>;
 
 template <class _Ap, class _Bp>
-concept derived_from =             //
-    std::is_base_of_v<_Bp, _Ap> && //
-    std::is_convertible_v<const volatile _Ap*, const volatile _Bp*>;
+concept derived_from =              //
+    STDEXEC_IS_BASE_OF(_Bp, _Ap) && //
+    STDEXEC_IS_CONVERTIBLE_TO(const volatile _Ap*, const volatile _Bp*);
 
 template <class _From, class _To>
-concept convertible_to =                 //
-    std::is_convertible_v<_From, _To> && //
+concept convertible_to =                     //
+    STDEXEC_IS_CONVERTIBLE_TO(_From, _To) && //
     requires(_From (&__fun)()) { static_cast<_To>(__fun()); };
 
 template <class _Ty>
diff --git a/include/sdbusplus/async/stdexec/env.hpp b/include/sdbusplus/async/stdexec/env.hpp
index 1ec7a6e..0beaf08 100644
--- a/include/sdbusplus/async/stdexec/env.hpp
+++ b/include/sdbusplus/async/stdexec/env.hpp
@@ -187,7 +187,7 @@
 
     __operation(_Sender&& __sndr, auto&& __rcvr, auto&& __env) :
         __base_t{(decltype(__rcvr))__rcvr, (decltype(__env))__env},
-        __state_{connect((_Sender&&)__sndr, __receiver_t{{}, this})}
+        __state_{stdexec::connect((_Sender&&)__sndr, __receiver_t{{}, this})}
     {}
 
     friend void tag_invoke(start_t, __operation& __self) noexcept
@@ -200,7 +200,6 @@
 struct __sender
 {
     using _Sender = stdexec::__t<_SenderId>;
-    using is_sender = void;
 
     template <class _Receiver>
     using __receiver_t = stdexec::__t<__receiver<__id<_Receiver>, _Env>>;
@@ -210,6 +209,7 @@
 
     struct __t
     {
+        using is_sender = void;
         using __id = __sender;
         _Sender __sndr_;
         _Env __env_;
diff --git a/include/sdbusplus/async/stdexec/execution.hpp b/include/sdbusplus/async/stdexec/execution.hpp
index 36e85bd..981de5d 100644
--- a/include/sdbusplus/async/stdexec/execution.hpp
+++ b/include/sdbusplus/async/stdexec/execution.hpp
@@ -44,20 +44,39 @@
 #pragma diag_suppress type_qualifiers_ignored_on_reference
 #endif
 
-#ifdef STDEXEC_ENABLE_R5_DEPRECATIONS
-#define STDEXEC_R5_SENDER_DEPR_WARNING                                                    \
-    [[deprecated(                                                                         \
-        "Deprecated sender type detected. Please update the type to satisfy the boolean " \
-        "stdexec::enable_sender<S> trait. "                                               \
-        "Defining a member type alias named 'is_sender' is one way to do this.")]]
-#define STDEXEC_R5_RECEIVER_DEPR_WARNING                                                              \
-    [[deprecated(                                                                                     \
-        "Deprecated receiver type detected. Please update the type for to satisfy the boolean "       \
-        "stdexec::enable_receiver<R> trait. Defining a member type alias named 'is_receiver' is one " \
-        "way to do this.")]]
+#ifndef STDEXEC_DISABLE_R5_DEPRECATION_WARNINGS
+#define STDEXEC_R5_SENDER_DEPRECATION_WARNING                                  \
+    [[deprecated(                                                              \
+        "Deprecated sender type detected. "                                    \
+        "Please give the type a nested `is_sender` type alias, or "            \
+        "specialize stdexec::enable_sender<your-sender-type> to be `true`. "   \
+        "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_RECEIVER_DEPRECATION_WARNING                                 \
+    [[deprecated(                                                               \
+        "Deprecated receiver type detected. "                                   \
+        "Please give the type a nested `is_receiver` type alias, or "           \
+        "specialize stdexec::enable_receiver<your-receiver-type> to be `true`." \
+        "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_DEPENDENT_COMPLETION_SIGNATURES_DEPRECATION_WARNING                 \
+    [[deprecated(                                                                      \
+        "The `dependent_completion_signatures<>` type is deprecated. There is "        \
+        "no need to define a customization of `get_completion_signatures` for "        \
+        "sender types whose completions are dependent on the receiver's environment. " \
+        "Give your sender type a nested `is_sender` type alias instead, "              \
+        "specialize stdexec::enable_sender<your-sender-type> to be `true`. "           \
+        "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
+#define STDEXEC_R5_NO_ENV_DEPRECATION_WARNING                                          \
+    [[deprecated(                                                                      \
+        "The `no_env` type is deprecated. The stdexec library no longer needs to use " \
+        "it to probe a type for satisfaction of the `sender` concept. "                \
+        "Give your sender type a nested `is_sender` type alias instead, or "           \
+        "specialize stdexec::enable_sender<your-sender-type> to be `true`. "           \
+        "To suppress this deprecation warning, define `STDEXEC_DISABLE_R5_DEPRECATIONS`.")]]
 #else
-#define STDEXEC_R5_SENDER_DEPR_WARNING
-#define STDEXEC_R5_RECEIVER_DEPR_WARNING
+#define STDEXEC_R5_SENDER_DEPRECATION_WARNING
+#define STDEXEC_R5_RECEIVER_DEPRECATION_WARNING
+#define STDEXEC_R5_DEPENDENT_COMPLETION_SIGNATURES_DEPRECATION_WARNING
+#define STDEXEC_R5_NO_ENV_DEPRECATION_WARNING
 #endif
 
 #define STDEXEC_LEGACY_R5_CONCEPTS() 1
@@ -297,8 +316,20 @@
 inline constexpr get_delegatee_scheduler_t get_delegatee_scheduler{};
 inline constexpr get_allocator_t get_allocator{};
 inline constexpr get_stop_token_t get_stop_token{};
+#if !STDEXEC_GCC() || defined(__OPTIMIZE__)
 template <__completion_tag _CPO>
 inline constexpr get_completion_scheduler_t<_CPO> get_completion_scheduler{};
+#else
+template <>
+inline constexpr get_completion_scheduler_t<set_value_t>
+    get_completion_scheduler<set_value_t>{};
+template <>
+inline constexpr get_completion_scheduler_t<set_error_t>
+    get_completion_scheduler<set_error_t>{};
+template <>
+inline constexpr get_completion_scheduler_t<set_stopped_t>
+    get_completion_scheduler<set_stopped_t>{};
+#endif
 
 template <class _Tag>
 concept __forwarding_query = forwarding_query(_Tag{});
@@ -353,10 +384,10 @@
     STDEXEC_NO_UNIQUE_ADDRESS _Env __env_;
 
     template <__forwarding_query _Tag>
-        requires __callable<_Tag, const _Env&>
+        requires tag_invocable<_Tag, const _Env&>
     friend auto tag_invoke(_Tag, const __env_fwd& __self) //
-        noexcept(__nothrow_callable<_Tag, const _Env&>)
-            -> __call_result_t<_Tag, const _Env&>
+        noexcept(nothrow_tag_invocable<_Tag, const _Env&>)
+            -> tag_invoke_result_t<_Tag, const _Env&>
     {
         return _Tag()(__self.__env_);
     }
@@ -376,10 +407,10 @@
     }
 
     template <class _Tag>
-        requires __callable<_Tag, const _Env&>
+        requires tag_invocable<_Tag, const _Env&>
     friend auto tag_invoke(_Tag, const __env_join& __self) //
-        noexcept(__nothrow_callable<_Tag, const _Env&>)
-            -> __call_result_t<_Tag, const _Env&>
+        noexcept(nothrow_tag_invocable<_Tag, const _Env&>)
+            -> tag_invoke_result_t<_Tag, const _Env&>
     {
         return _Tag()(__self.__env_);
     }
@@ -841,9 +872,17 @@
 
 /////////////////////////////////////////////////////////////////////////////
 // [execution.receivers]
+struct __receiver_base
+{};
+
 template <class _Receiver>
-inline constexpr bool enable_receiver = //
-    requires { typename _Receiver::is_receiver; };
+concept __enable_receiver = //
+    requires { typename _Receiver::is_receiver; } ||
+    STDEXEC_IS_BASE_OF(__receiver_base, _Receiver);
+
+template <class _Receiver>
+inline constexpr bool enable_receiver =
+    __enable_receiver<_Receiver>; // NOT TO SPEC
 
 //   NOT TO SPEC:
 //   As we upgrade the receiver related entities from R5 to R7,
@@ -1904,15 +1943,15 @@
 struct connect_t;
 
 template <class _Tp>
-STDEXEC_R5_SENDER_DEPR_WARNING //
+STDEXEC_R5_SENDER_DEPRECATION_WARNING //
     void
-    __update_sender_type_to_p2300r7_by_adding_enable_sender_trait()
+    _PLEASE_UPDATE_YOUR_SENDER_TYPE()
 {}
 
 template <class _Tp>
-STDEXEC_R5_RECEIVER_DEPR_WARNING //
+STDEXEC_R5_RECEIVER_DEPRECATION_WARNING //
     void
-    __update_receiver_type_to_p2300r7_by_adding_enable_receiver_trait()
+    _PLEASE_UPDATE_YOUR_RECEIVER_TYPE()
 {}
 
 template <class _Sender, class _Receiver>
@@ -1929,12 +1968,10 @@
     {
         // Report that 2300R5-style senders and receivers are deprecated:
         if constexpr (!enable_sender<__decay_t<_Sender>>)
-            __update_sender_type_to_p2300r7_by_adding_enable_sender_trait<
-                __decay_t<_Sender>>();
+            _PLEASE_UPDATE_YOUR_SENDER_TYPE<__decay_t<_Sender>>();
 
         if constexpr (!enable_receiver<__decay_t<_Receiver>>)
-            __update_receiver_type_to_p2300r7_by_adding_enable_receiver_trait<
-                __decay_t<_Receiver>>();
+            _PLEASE_UPDATE_YOUR_RECEIVER_TYPE<__decay_t<_Receiver>>();
 
         if constexpr (__connectable_with_tag_invoke<_Sender, _Receiver>)
         {
@@ -2049,6 +2086,8 @@
 template <class _Value>
 struct __receiver_base
 {
+    using is_receiver = void;
+
     template <same_as<set_value_t> _Tag, class... _Us>
         requires constructible_from<__value_or_void_t<_Value>, _Us...>
     friend void tag_invoke(_Tag, __receiver_base&& __self,
@@ -2411,11 +2450,11 @@
 template <class _ReceiverId>
 struct __receiver
 {
-    using is_receiver = void;
     using _Receiver = stdexec::__t<_ReceiverId>;
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
         __operation_base<_ReceiverId>* __op_state_;
 
@@ -2539,6 +2578,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __detached_receiver;
         STDEXEC_NO_UNIQUE_ADDRESS _Env __env_;
 
@@ -2759,6 +2799,7 @@
 template <class _Fun>
 struct __as_receiver
 {
+    using is_receiver = void;
     _Fun __fun_;
 
     template <same_as<set_value_t> _Tag>
@@ -2931,7 +2972,7 @@
     requires __decays_to<_Tp, _Tp>
 {
     static_assert(std::is_reference_v<__copy_cvref_t<_Up&&, _Tp>>);
-    static_assert(std::is_base_of_v<_Tp, __decay_t<_Up>>);
+    static_assert(STDEXEC_IS_BASE_OF(_Tp, __decay_t<_Up>));
     return (__copy_cvref_t<_Up&&, _Tp>)(_Up&&)u;
 }
 
@@ -3032,7 +3073,7 @@
 template <__class _Derived, class _Base>
 struct receiver_adaptor
 {
-    class __t : __adaptor_base<_Base>
+    class __t : __adaptor_base<_Base>, __receiver_base
     {
         friend _Derived;
         _DEFINE_MEMBER(set_value);
@@ -3269,6 +3310,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
         __data* __op_;
 
@@ -3451,6 +3493,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
 
         _Receiver __rcvr_;
@@ -3607,6 +3650,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
         _Receiver __rcvr_;
         STDEXEC_NO_UNIQUE_ADDRESS _Fun __fun_;
@@ -3955,6 +3999,7 @@
         stdexec::__t<__sh_state<_CvrefSenderId, _EnvId>>& __sh_state_;
 
       public:
+        using is_receiver = void;
         using __id = __receiver;
 
         template <__completion_tag _Tag, class... _As>
@@ -4311,6 +4356,7 @@
             __shared_state_;
 
       public:
+        using is_receiver = void;
         using __id = __receiver;
 
         explicit __t(stdexec::__t<__sh_state<_CvrefSenderId, _EnvId>>&
@@ -4769,6 +4815,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver_;
 
         template <__one_of<_Set> _Tag, class... _As>
@@ -5465,6 +5512,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver2;
         stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
             __op_state_;
@@ -5510,6 +5558,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         stdexec::__t<__operation1<_SchedulerId, _CvrefSenderId, _ReceiverId>>*
             __op_state_;
 
@@ -6059,6 +6108,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
         using _Receiver = stdexec::__t<_ReceiverId>;
         _Receiver __rcvr_;
@@ -6378,6 +6428,7 @@
 
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
 
         template <class _Error>
@@ -6975,6 +7026,7 @@
 {
     struct __t
     {
+        using is_receiver = void;
         using __id = __receiver;
         __state<_Values...>* __state_;
         run_loop* __loop_;