Skip to content

Commit 40efbc1

Browse files
ispetersclaude
andcommitted
Test the completion domain function reports when started elsewhere
A `function` reports the completion domains its type declares, whatever environment it's connected in. When its implementation completes inline, as `just` does, the operation actually completes wherever the caller started it, so the reported domain can differ from the domain that `just` itself would report in the same environment. This diff adds a test that pins that behaviour: * in an environment whose `get_domain` names a domain derived from `default_domain`, `just` reports that domain while a `function` wrapping `just` reports `default_domain`; * forwarding `get_domain` through a declared query doesn't change the reported domain; * a `function` that forwards a domain derived from `default_domain` but declares the default is still constructible, since the constraint accepts the declared domain when it's the common domain of the declared and actual ones, while an unrelated forwarded domain is rejected; and * declaring the forwarded domain in `attrs<...>` makes the `function` report it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent cee246e commit 40efbc1

1 file changed

Lines changed: 57 additions & 0 deletions

File tree

‎test/exec/test_function.cpp‎

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,63 @@ namespace
12291229
}
12301230
}
12311231

1232+
TEST_CASE("function reports its declared completion domain wherever it's started",
1233+
"[types][function]")
1234+
{
1235+
// A function's completion domain comes from its type, not from the
1236+
// environment it's connected in, even when its implementation completes
1237+
// inline and so actually completes wherever the caller started it.
1238+
auto caller_env = ex::prop(ex::get_domain, domain());
1239+
1240+
SECTION("an inline-completing implementation doesn't report the caller's domain")
1241+
{
1242+
exec::function<void()> fn(ex::just);
1243+
1244+
auto just_domain = get_completion_domain<ex::set_value_t>(ex::get_env(ex::just()),
1245+
caller_env);
1246+
auto fn_domain = get_completion_domain<ex::set_value_t>(ex::get_env(fn), caller_env);
1247+
1248+
STATIC_REQUIRE(std::same_as<domain, decltype(just_domain)>);
1249+
STATIC_REQUIRE(std::same_as<ex::default_domain, decltype(fn_domain)>);
1250+
}
1251+
1252+
SECTION("forwarding the caller's domain doesn't change what's reported")
1253+
{
1254+
using function = exec::function<void(), exec::queries<domain(ex::get_domain_t) noexcept>>;
1255+
1256+
function fn(ex::just);
1257+
auto fn_domain = get_completion_domain<ex::set_value_t>(ex::get_env(fn), caller_env);
1258+
1259+
STATIC_REQUIRE(std::same_as<ex::default_domain, decltype(fn_domain)>);
1260+
}
1261+
1262+
SECTION("a forwarded domain is accepted under the default only if it derives from it")
1263+
{
1264+
struct unrelated_domain
1265+
{};
1266+
1267+
using derived = exec::function<void(), exec::queries<domain(ex::get_domain_t) noexcept>>;
1268+
using unrelated =
1269+
exec::function<void(), exec::queries<unrelated_domain(ex::get_domain_t) noexcept>>;
1270+
1271+
STATIC_REQUIRE(std::constructible_from<derived, ex::just_t>);
1272+
STATIC_REQUIRE(!std::constructible_from<unrelated, ex::just_t>);
1273+
}
1274+
1275+
SECTION("declaring the forwarded domain reports it")
1276+
{
1277+
using function =
1278+
exec::function<void(),
1279+
exec::queries<domain(ex::get_domain_t) noexcept>,
1280+
exec::attrs<domain(ex::get_completion_domain_t<ex::set_value_t>)>>;
1281+
1282+
function fn(ex::just);
1283+
auto fn_domain = get_completion_domain<ex::set_value_t>(ex::get_env(fn), caller_env);
1284+
1285+
STATIC_REQUIRE(std::same_as<domain, decltype(fn_domain)>);
1286+
}
1287+
}
1288+
12321289
template <auto Tag>
12331290
using custom_domain_for =
12341291
exec::attrs<domain(ex::get_completion_domain_t<std::remove_cvref_t<decltype(Tag)>>)>;

0 commit comments

Comments
 (0)