Skip to content

Commit 08eb3f8

Browse files
Fix read_with_default connect noexcept (#2208)
* Fix read_with_default connect noexcept * Format Clang sources * Format read_with_default changes * Guard read_with_default exception test --------- Co-authored-by: Eric Niebler <eniebler@nvidia.com>
1 parent a609c73 commit 08eb3f8

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

include/exec/env.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,10 @@ namespace experimental::execution
180180

181181
template <__decays_to<__sender> _Self, class _Receiver>
182182
constexpr STDEXEC_EXPLICIT_THIS_BEGIN(auto connect)(this _Self&& __self, _Receiver __rcvr)
183-
noexcept(std::is_nothrow_move_constructible_v<_Receiver>)
184-
-> __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>
183+
noexcept(__nothrow_constructible_from<
184+
__opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>,
185+
__default_t<env_of_t<_Receiver>>,
186+
_Receiver>) -> __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>
185187
{
186188
using __opstate_t = __opstate<_Query, __default_t<env_of_t<_Receiver>>, _Receiver>;
187189
return __opstate_t{static_cast<_Self&&>(__self).__default_,

test/exec/test_env.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,53 @@
2323

2424
namespace
2525
{
26+
#if !STDEXEC_NO_STDCPP_EXCEPTIONS()
27+
struct missing_query : STDEXEC::__query<missing_query>
28+
{
29+
using STDEXEC::__query<missing_query>::operator();
30+
};
31+
32+
struct default_move_error
33+
{};
34+
35+
struct throwing_default
36+
{
37+
explicit throwing_default(bool* throw_on_move) noexcept
38+
: throw_on_move_{throw_on_move}
39+
{}
40+
41+
throwing_default(throwing_default const &) noexcept = default;
42+
43+
throwing_default(throwing_default&& other)
44+
: throw_on_move_{other.throw_on_move_}
45+
{
46+
if (*throw_on_move_)
47+
{
48+
throw default_move_error{};
49+
}
50+
}
51+
52+
bool* throw_on_move_;
53+
};
54+
55+
struct read_with_default_receiver
56+
{
57+
using receiver_concept = STDEXEC::receiver_tag;
58+
59+
template <class _Value>
60+
void set_value(_Value&&) noexcept
61+
{}
62+
63+
void set_error(std::exception_ptr) noexcept {}
64+
void set_stopped() noexcept {}
65+
66+
auto get_env() const noexcept -> STDEXEC::env<>
67+
{
68+
return {};
69+
}
70+
};
71+
#endif // !STDEXEC_NO_STDCPP_EXCEPTIONS()
72+
2673
// Two dummy properties:
2774
constexpr struct Foo
2875
: STDEXEC::__query<Foo>
@@ -57,6 +104,18 @@ namespace
57104
CHECK(bar(e4) == 43);
58105
}
59106

107+
#if !STDEXEC_NO_STDCPP_EXCEPTIONS()
108+
TEST_CASE("read_with_default connect propagates default move exceptions", "[env]")
109+
{
110+
bool throw_on_move = false;
111+
auto sndr = exec::read_with_default(missing_query{}, throwing_default{&throw_on_move});
112+
throw_on_move = true;
113+
114+
STATIC_REQUIRE_FALSE(noexcept(std::move(sndr).connect(read_with_default_receiver{})));
115+
CHECK_THROWS_AS(std::move(sndr).connect(read_with_default_receiver{}), default_move_error);
116+
}
117+
#endif // !STDEXEC_NO_STDCPP_EXCEPTIONS()
118+
60119
TEST_CASE("without propagates environment move exceptions", "[env]")
61120
{
62121
struct missing_query : STDEXEC::__query<missing_query>

0 commit comments

Comments
 (0)