The block-wise ASCII fast path in scalar::utf8::validate_with_counts uses
std::memcpy, which is not usable during constant evaluation. The function
is marked simdutf_constexpr23 and implementation.h dispatches to it from an
'if consteval' branch, so any constant-evaluated call with 16 or more bytes
failed to compile. Guard the fast path with 'if !consteval', exactly as
scalar::utf8::validate() in the same header already does.
Adds constexpr assertions to the boundary tests; they reproduce the failure
without the guard and are exercised by the C++23 leg of CI.
Targets simdunicode-port (the branch behind simdutf#974).
The problem
scalar::utf8::validate_with_counts is marked simdutf_constexpr23, and the span overload in implementation.h dispatches to it from an if consteval branch. But its block-wise ASCII fast path calls std::memcpy, which is not usable during constant evaluation. So any constant-evaluated call with 16 or more bytes fails to compile:
Inputs shorter than 16 bytes never reach the fast path, which is why this went unnoticed.
scalar::utf8::validate() in the same header already handles this with an if !consteval guard; validate_with_counts was ported without it.
The fix
Wrap the fast path in the same #if SIMDUTF_CPLUSPLUS23 / if !consteval / #endif guard used by validate(), and match its uint64_t v1{} initialization.
Also adds constexpr assertions to tests/validate_utf8_with_counts_boundary_tests.cpp (guarded by SIMDUTF_CPLUSPLUS23 && SIMDUTF_SPAN, no CMake change needed), covering a pure-ASCII input longer than one fast-path block, a long ASCII run followed by 2-, 3- and 4-byte sequences, and an invalid byte past the first block.
Verification
On a Xeon Gold 6548N / Fedora box:
ubuntu24-cxxstandards.yml runs cppversion: [17, 20, 23], so the C++23 leg of CI exercises the new assertions.
No behavioural change at run time: the guard only affects constant evaluation.