From d3a4e456bf838436ef788d4b419fc41215db6fdb Mon Sep 17 00:00:00 2001 From: Minh Vu Date: Wed, 12 Aug 2026 01:24:35 +0200 Subject: [PATCH 1/2] Fix nvexec upon_error callable forwarding --- include/nvexec/stream/upon_error.cuh | 2 +- test/nvexec/upon_error.cpp | 31 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/nvexec/stream/upon_error.cuh b/include/nvexec/stream/upon_error.cuh index 38350b9ff..9bd367bbe 100644 --- a/include/nvexec/stream/upon_error.cuh +++ b/include/nvexec/stream/upon_error.cuh @@ -172,7 +172,7 @@ namespace nv::execution::_strm static_cast(self).sndr_, static_cast(rcvr), [&](_strm::opstate_base& stream_provider) -> receiver_t - { return receiver_t(self.fun_, stream_provider); }); + { return receiver_t(static_cast(self).fun_, stream_provider); }); } STDEXEC_EXPLICIT_THIS_END(connect) diff --git a/test/nvexec/upon_error.cpp b/test/nvexec/upon_error.cpp index df3f1c491..8d049571b 100644 --- a/test/nvexec/upon_error.cpp +++ b/test/nvexec/upon_error.cpp @@ -1,6 +1,8 @@ #include #include +#include + #include "common.cuh" #include "nvexec/stream_context.cuh" @@ -11,6 +13,23 @@ using nvexec::is_on_gpu; namespace { + struct move_only_error_handler + { + move_only_error_handler() = default; + move_only_error_handler(move_only_error_handler const &) = delete; + + STDEXEC_ATTRIBUTE(host, device) + move_only_error_handler(move_only_error_handler &&) = default; + + STDEXEC_ATTRIBUTE(host, device) auto operator()(int error) const -> int + { + return error; + } + }; + + static_assert(std::is_trivially_copyable_v); + static_assert(!std::is_copy_constructible_v); + TEST_CASE("nvexec upon_error returns a sender", "[cuda][stream][adaptors][upon_error]") { nvexec::stream_context stream_ctx{}; @@ -21,6 +40,18 @@ namespace (void) snd; } + TEST_CASE("nvexec upon_error supports move-only function objects", + "[cuda][stream][adaptors][upon_error]") + { + nvexec::stream_context stream_ctx{}; + + auto snd = ex::just_error(42) | ex::continues_on(stream_ctx.get_scheduler()) + | ex::upon_error(move_only_error_handler{}); + auto const [result] = STDEXEC::sync_wait(std::move(snd)).value(); + + REQUIRE(result == 42); + } + TEST_CASE("nvexec upon_error executes on GPU", "[cuda][stream][adaptors][upon_error]") { nvexec::stream_context stream_ctx{}; From db17aab5e1bc4769c5f2500aa4ad917c88386fab Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Thu, 13 Aug 2026 12:29:22 -0700 Subject: [PATCH 2/2] move receiver into _strm::opstate_base --- include/nvexec/stream/common.cuh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/nvexec/stream/common.cuh b/include/nvexec/stream/common.cuh index 1e2a03ac5..4aef7a2bf 100644 --- a/include/nvexec/stream/common.cuh +++ b/include/nvexec/stream/common.cuh @@ -663,7 +663,7 @@ namespace nv::execution opstate_base(OuterReceiver rcvr, context ctx) : ctx_(ctx) - , rcvr_(rcvr) + , rcvr_(static_cast(rcvr)) , stream_provider_(borrows_stream, ctx) {}