From 81174ffe9023d5b711bdb293d6db5df53fc6f48b Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 26 Apr 2026 12:54:05 -0700 Subject: [PATCH 1/3] make `STDEXEC_ASSERT` usable during constant evaluation --- include/stdexec/__detail/__config.hpp | 41 +++++++++++++++++------ include/stdexec/__detail/__schedulers.hpp | 5 ++- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 622243e0e..4abbc4615 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -659,19 +659,40 @@ namespace STDEXEC } else #endif -#ifdef STDEXEC_ASSERT -# error "Redefinition of STDEXEC_ASSERT is not permitted. Define STDEXEC_ASSERT_FN instead." +#if defined(STDEXEC_ASSERT) +// nothing to do, user has provided their own assertion macro +#elif defined(STDEXEC_ASSERT_FN) +// legacy way to customize assertions, still supported for backward compatibility +# define STDEXEC_ASSERT(_XP) STDEXEC_ASSERT_FN(_XP) +#else +# define STDEXEC_ASSERT(_XP) \ + do \ + { \ + STDEXEC_PRAGMA_PUSH() \ + STDEXEC_PRAGMA_IGNORE_GNU("-Wtautological-compare") \ + STDEXEC_IF_CONSTEVAL \ + { \ + if (!(_XP)) \ + STDEXEC::__throw_assertion_failure(); \ + } \ + else \ + { \ + assert(_XP); \ + } \ + STDEXEC_PRAGMA_POP() \ + } while (false) #endif -#define STDEXEC_ASSERT(_XP) \ - do { \ - /*static_assert(noexcept(_XP));*/ \ - STDEXEC_ASSERT_FN(_XP); \ - } while (false) +namespace STDEXEC +{ + struct __assertion_failure + {}; -#ifndef STDEXEC_ASSERT_FN -# define STDEXEC_ASSERT_FN assert -#endif + inline void __throw_assertion_failure() + { + throw __assertion_failure{}; + } +} // namespace STDEXEC #define STDEXEC_AUTO_RETURN(...) \ noexcept(noexcept(__VA_ARGS__))->decltype(__VA_ARGS__) { \ diff --git a/include/stdexec/__detail/__schedulers.hpp b/include/stdexec/__detail/__schedulers.hpp index f9a503e8d..5d6b32201 100644 --- a/include/stdexec/__detail/__schedulers.hpp +++ b/include/stdexec/__detail/__schedulers.hpp @@ -248,7 +248,7 @@ namespace STDEXEC env_of_t>, _Env const &...>) { - STDEXEC_ASSERT_FN(__sch == __read_query_t{}(get_env(__sch.schedule()), __env...)); + STDEXEC_ASSERT(__sch == __read_query_t{}(get_env(__sch.schedule()), __env...)); } return __sch; } @@ -265,8 +265,7 @@ namespace STDEXEC __call_result_t, _Attrs const &, _Env const &...>; static_assert(__same_as<__domain_t, __detail::__scheduler_domain_t<_Sch, _Env const &...>>, "the sender claims to complete on a domain that is not the domain of its " - "completion " - "scheduler"); + "completion scheduler"); } return __sch; } From 0e85ce3cd2256596ae120d2bdd88e274038c576c Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Sun, 26 Apr 2026 17:54:05 -0700 Subject: [PATCH 2/3] do not generate code in NDEBUG mode --- include/stdexec/__detail/__config.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 4abbc4615..9d3352c0b 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -379,7 +379,8 @@ namespace STDEXEC::__std #elif STDEXEC_EDG() # define STDEXEC_PRAGMA_PUSH() \ STDEXEC_PRAGMA(diagnostic push) \ - STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_number) STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_tag) + STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_number) \ + STDEXEC_PRAGMA_IGNORE_EDG(invalid_error_tag) # define STDEXEC_PRAGMA_POP() STDEXEC_PRAGMA(diagnostic pop) # define STDEXEC_PRAGMA_IGNORE_EDG(...) STDEXEC_PRAGMA(diag_suppress __VA_ARGS__) #elif STDEXEC_CLANG() || STDEXEC_GCC() @@ -664,6 +665,8 @@ namespace STDEXEC #elif defined(STDEXEC_ASSERT_FN) // legacy way to customize assertions, still supported for backward compatibility # define STDEXEC_ASSERT(_XP) STDEXEC_ASSERT_FN(_XP) +#elif defined(NDEBUG) +# define STDEXEC_ASSERT(_XP) ((void)0) #else # define STDEXEC_ASSERT(_XP) \ do \ From d12619a880a5d6455832120835ca88b89af2e8b7 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Mon, 27 Apr 2026 11:44:59 -0700 Subject: [PATCH 3/3] avoid nvc++ pragma push/pop bug --- include/stdexec/__detail/__config.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/stdexec/__detail/__config.hpp b/include/stdexec/__detail/__config.hpp index 9d3352c0b..3106b08fa 100644 --- a/include/stdexec/__detail/__config.hpp +++ b/include/stdexec/__detail/__config.hpp @@ -653,11 +653,16 @@ namespace STDEXEC #if defined(__cpp_if_consteval) && __cpp_if_consteval >= 202106L # define STDEXEC_IF_CONSTEVAL if consteval # define STDEXEC_IF_NOT_CONSTEVAL if !consteval +#elif STDEXEC_GCC() +# define STDEXEC_IF_CONSTEVAL \ + STDEXEC_PRAGMA_PUSH() \ + STDEXEC_PRAGMA_IGNORE_GNU("-Wtautological-compare") \ + if (std::is_constant_evaluated()) \ + STDEXEC_PRAGMA_POP() +# define STDEXEC_IF_NOT_CONSTEVAL STDEXEC_IF_CONSTEVAL {} else #else -# define STDEXEC_IF_CONSTEVAL if (std::is_constant_evaluated()) -# define STDEXEC_IF_NOT_CONSTEVAL \ - if (std::is_constant_evaluated()) { \ - } else +# define STDEXEC_IF_CONSTEVAL if (std::is_constant_evaluated()) +# define STDEXEC_IF_NOT_CONSTEVAL STDEXEC_IF_CONSTEVAL {} else #endif #if defined(STDEXEC_ASSERT) @@ -665,14 +670,10 @@ namespace STDEXEC #elif defined(STDEXEC_ASSERT_FN) // legacy way to customize assertions, still supported for backward compatibility # define STDEXEC_ASSERT(_XP) STDEXEC_ASSERT_FN(_XP) -#elif defined(NDEBUG) -# define STDEXEC_ASSERT(_XP) ((void)0) #else # define STDEXEC_ASSERT(_XP) \ do \ { \ - STDEXEC_PRAGMA_PUSH() \ - STDEXEC_PRAGMA_IGNORE_GNU("-Wtautological-compare") \ STDEXEC_IF_CONSTEVAL \ { \ if (!(_XP)) \ @@ -682,7 +683,6 @@ namespace STDEXEC { \ assert(_XP); \ } \ - STDEXEC_PRAGMA_POP() \ } while (false) #endif