From 0e21d9549aa1e3a53e7505da2f7f9a3a647b1eeb Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Sun, 16 Aug 2026 02:15:37 +0200 Subject: [PATCH 1/2] Preserve libdispatch bulk child sender value category --- include/exec/libdispatch_queue.hpp | 3 +- test/exec/test_libdispatch.cpp | 49 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/include/exec/libdispatch_queue.hpp b/include/exec/libdispatch_queue.hpp index e9ded94cb..82c51caf7 100644 --- a/include/exec/libdispatch_queue.hpp +++ b/include/exec/libdispatch_queue.hpp @@ -537,7 +537,8 @@ namespace experimental::execution bulk_op_state(libdispatch_queue &queue, Shape shape, Fun fun, CvSender &&sndr, Receiver rcvr) : shared_state_(std::move(rcvr), shape, fun) - , inner_op_{STDEXEC::connect(std::move(sndr), bulk_rcvr{shared_state_, queue})} + , inner_op_{STDEXEC::connect(static_cast(sndr), + bulk_rcvr{shared_state_, queue})} {} void start() & noexcept diff --git a/test/exec/test_libdispatch.cpp b/test/exec/test_libdispatch.cpp index 2f242b117..6e9569dbd 100644 --- a/test/exec/test_libdispatch.cpp +++ b/test/exec/test_libdispatch.cpp @@ -25,6 +25,42 @@ namespace { + struct lvalue_connect_sender + { + using sender_concept = STDEXEC::sender_tag; + + template + static consteval auto get_completion_signatures() + -> STDEXEC::completion_signatures + { + return {}; + } + + auto get_env() const noexcept -> STDEXEC::env<> + { + return {}; + } + + template + struct operation + { + using operation_state_concept = STDEXEC::operation_state_tag; + + Receiver receiver_; + + void start() & noexcept + { + STDEXEC::set_value(std::move(receiver_), 42); + } + }; + + template + auto connect(Receiver receiver) & noexcept -> operation + { + return {std::move(receiver)}; + } + }; + TEST_CASE("libdispatch queue should be able to process tasks") { exec::libdispatch_queue queue; @@ -201,4 +237,17 @@ namespace CHECK(seen == 42); CHECK_FALSE(value.moved_from); } + + TEST_CASE("libdispatch bulk connects an lvalue child sender as an lvalue") + { + exec::libdispatch_queue queue; + auto fun = [](int, int &) noexcept {}; + using sender_t = exec::__libdispatch::bulk_sender; + + sender_t sender{queue, lvalue_connect_sender{}, 0, std::move(fun)}; + auto result = STDEXEC::sync_wait(sender); + + REQUIRE(result.has_value()); + CHECK(std::get<0>(*result) == 42); + } } // namespace From b69ba18e200fe281968f2dab7b6c1ed711f9cdb4 Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Sun, 16 Aug 2026 20:49:54 +0200 Subject: [PATCH 2/2] Format libdispatch bulk changes --- include/exec/libdispatch_queue.hpp | 4 ++-- test/exec/test_libdispatch.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/exec/libdispatch_queue.hpp b/include/exec/libdispatch_queue.hpp index 82c51caf7..24bf27221 100644 --- a/include/exec/libdispatch_queue.hpp +++ b/include/exec/libdispatch_queue.hpp @@ -537,8 +537,8 @@ namespace experimental::execution bulk_op_state(libdispatch_queue &queue, Shape shape, Fun fun, CvSender &&sndr, Receiver rcvr) : shared_state_(std::move(rcvr), shape, fun) - , inner_op_{STDEXEC::connect(static_cast(sndr), - bulk_rcvr{shared_state_, queue})} + , inner_op_{ + STDEXEC::connect(static_cast(sndr), bulk_rcvr{shared_state_, queue})} {} void start() & noexcept diff --git a/test/exec/test_libdispatch.cpp b/test/exec/test_libdispatch.cpp index 6e9569dbd..465411407 100644 --- a/test/exec/test_libdispatch.cpp +++ b/test/exec/test_libdispatch.cpp @@ -30,8 +30,8 @@ namespace using sender_concept = STDEXEC::sender_tag; template - static consteval auto get_completion_signatures() - -> STDEXEC::completion_signatures + static consteval auto + get_completion_signatures() -> STDEXEC::completion_signatures { return {}; }