Skip to content

docs: state unwritten contracts in doc comments#236

Closed
cameroncuster wants to merge 1 commit into
devfrom
doc-contracts
Closed

docs: state unwritten contracts in doc comments#236
cameroncuster wants to merge 1 commit into
devfrom
doc-contracts

Conversation

@cameroncuster

Copy link
Copy Markdown
Member

Documents unwritten contracts — preconditions the code relies on but the //! doc comments didn't state. Comment-only change (0 code lines touched), plus two line-pin bumps in the cppcheck suppression list.

Each contract was verified against the exact line that breaks if it's violated:

File Contract added What happens if violated
graphs/dijkstra.hpp requires weights >= 0 silently wrong distances
strings/binary_trie.hpp requires 0 <= num < 2^61; walk requires a non-empty trie wrong result (bits above 60 ignored; walk on empty trie follows -1)
math/mod_division.hpp requires gcd(y, mod) == 1 assert fires
math/matrix_related/row_reduce.hpp requires mod is prime mod_div asserts / wrong answer (needs every nonzero pivot invertible)
math/matrix_related/matrix_mult.hpp watch for overflow if T is an integer type silent overflow (fine with modint, as in tests)
graphs/uncommon/enumerate_triangles.hpp requires no self loops or multi edges self-loop u==v makes tie comparison degenerate; multi-edges double-count
loops/submasks.hpp excludes the empty submask loop condition submask; stops before 0 — easy 4am surprise
math/derangements.hpp requires n >= 1 dp[0] = 1 on empty vector is UB
strings/kmp.hpp requires t non-empty pi[j - 1] with j==sz(t)==0 reads pi[-1]
trees/hld.hpp g is mutated (parent edges removed) caller reuses g afterward and gets a broken graph
trees/centroid_decomp.hpp g is mutated (edges removed) same
trees/edge_cd.hpp g is mutated (edges reordered/removed) same

Findings that were considered and deliberately NOT documented (checked against the code):

  • "trees must be rooted at 0 / connected" — universal convention across every tree structure in the repo; documenting it on 7 files individually adds noise, and vector<basic_string<int>> g(n) usage blocks already imply the shape
  • "n >= 1" on DSU/SCC/rmq etc. — constructors are safe on n=0 (empty vectors, loops don't run); only ops on nonexistent indices break, which is true of every container
  • rmq assert(l < r) — enforced by an assert already in the code, self-documenting
  • suffix_array 0 <= s[i] < max_num — already documented in that header
  • hungarian 1 <= n <= m — already documented (1<=i<=n<=m)
  • several sub-agent claims were simply wrong (e.g. "partitions breaks on n=0" — vector dp(0) + non-executing loop is fine; "xor_convolution power-of-2 undocumented" — it's in the @code block)

Validation:

  • diff outside the suppression list is 100% comment lines
  • clang-format --dry-run --Werror passes on all changed files
  • grep_clangformat_cppcheck.sh passes
  • affected tests compile: dijkstra, derangement, matrix_mult, matrix_determinant (row_reduce+mod_division), kmp, binary_trie

@cameroncuster cameroncuster deleted the doc-contracts branch July 8, 2026 15:48
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