Skip to content

zu-c holds the idiom item - #630

Merged
tamnd merged 1 commit into
mainfrom
c-idiom
Aug 22, 2026
Merged

tamnd merged 1 commit into
mainfrom
c-idiom

Conversation

@tamnd

@tamnd tamnd commented Aug 22, 2026

Copy link
Copy Markdown
Owner

zu-c's practice score goes from 50 to 67. The item is idiom, at 15, the largest single item on any card here: "The language's own shapes: how it iterates, how it releases a resource, how it awaits, what it raises. A binding that reads like the C ABI in another syntax is a binding nobody wants to write against."

67 rather than 75 because zu-c is scored out of 90: it owes no api-map, since the C names are zu.h and zu.h is generated in the engine, and no perf report.

before after
zu-c practice 50 67
missing reference, idiom, install, stability reference, install, stability

The work is tamnd/zu-c#9. Three parts.

A dropped return was a lost failure. Ninety of the calls in zu.hpp answer something a caller must not drop, and three of them said so. A try_ call answers a std::expected whose error half is the failure report, so conn.try_query(q); on a line of its own compiles, throws nothing, returns nothing and loses the reason. All ninety are [[nodiscard]] now, and it caught a real one in the existing suite on the first build.

The bug it found. zu.hpp read __cpp_lib_expected before <version> had defined it. An undefined identifier is nought in a preprocessor arithmetic expression, so ZU_HAS_EXPECTED came out 0 on GCC 13 at -std=c++23, where std::expected has been available since GCC 12, and the whole try_ half of the API went undeclared on a toolchain that has it. Worse than absent, it depended on include order: a translation unit that had already included <version> got a different zu.hpp than one that had not, in the same build.

Nothing said so, because test_expected.cpp is one #if with a single placeholder case in the #else for the C++20 floor. ctest ran the placeholder, printed Passed, and eleven cases about the half a caller who builds without exceptions depends on had not been compiled by anything. That branch now carries an #error: below C++23 there is nothing to run, but at C++23 and above this half missing is a broken build rather than a quiet one.

Printing. <format> was included at the top of the header and ZU_HAS_FORMAT defined beside it, and neither was used in the header, the tests, the examples or the README. There is now a to_string for every type worth printing and a std::formatter over each, one line apiece, so the C++20 floor gets the same text as C++23. No operator<<, because <ostream> would land in every translation unit that includes the header whether it prints or not.

test_idiom.cpp pins the shapes with concepts rather than prose: Result is a sized, common, random access range of Row and deliberately not a borrowed_range, so filtering a temporary result is a compile error where it was written rather than a use after free that works in a debug build; handles move and do not copy; exceptions descend from std::runtime_error; the value structs are std::regular.

The overview below was regenerated by cargo xtask clients, which still reports "7 clients, 5 of them tier 1, 4 at their tier's practice threshold". zu-c is not one of the four and should not be until its card is finished.

The largest item on any card here, at 15, and the last big one on
zu-c's. The card goes from 50 to 67 of the 90 it is scored out of, since
zu-c owes no api-map and no perf.

What landed is tamnd/zu-c#9. Ninety [[nodiscard]] attributes on the
calls whose return value is the failure report; a to_string and a
std::formatter for every type worth printing, which is what ZU_HAS_FORMAT
was for and had never been used for; and test_idiom.cpp, which is mostly
static_assert on purpose, because a Result being a random access range
and deliberately not a borrowed one is a promise the compiler should
keep at every call site rather than one a case checked once.

The sweep found a bug on its way through. zu.hpp read
__cpp_lib_expected before <version> had defined it, so ZU_HAS_EXPECTED
came out 0 on GCC 13 at -std=c++23 and the whole try_ half of the API
went undeclared on a toolchain that has it. It depended on include
order, so two translation units in one build got two different headers.
Nothing said so, because the suite for that half is one #if and
compiled down to a single placeholder case that passed. That file now
carries an #error on the floor branch: at C++23 and above, this half
missing is a broken build rather than a quiet one.

Left on the card: reference, install and stability, at 10 each.
@tamnd
tamnd merged commit b4e6579 into main Aug 22, 2026
32 of 40 checks passed
@tamnd
tamnd deleted the c-idiom branch August 22, 2026 17:44
@tamnd tamnd mentioned this pull request Aug 22, 2026
22 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant