Contracts for C

C’s Conservatism vs Language Evolution

  • Several comments argue C should stay small and stable, unlike Java, C#, or modern C++, which have grown complex.
  • Others counter that most other ecosystems evolved in response to developer demand; resistance to change in C has pushed people toward C++, Rust, Zig, etc.
  • There’s disagreement about how representative current C users are: some say “most C programmers don’t want new features,” others call this survivorship bias because many who wanted more features already left.

Contracts as a Feature for C

  • Some see contracts as a useful, opt‑in way to improve existing C codebases without rewrites; those uninterested can ignore them.
  • Others argue C already has assert and that contracts add syntax and complexity without solving core issues like memory safety, slices/spans, or a stronger standard library.
  • There’s prior art: Eiffel, Ada/SPARK, D, and tools like Frama‑C and “cake” are mentioned as richer or more formal contract systems.

Undefined Behavior and unreachable()

  • The proposed macro‑based contracts use unreachable() (C23) to turn contract violations into undefined behavior.
  • Critics say this is conceptually wrong: contracts should allow compilers to prove properties or produce diagnostics, not convert recoverable failures into UB that can be reordered or optimized away.
  • Some defend explicit UB markers as useful: they document impossible paths and help optimizers and static analyzers, but concede they’re not reliable runtime checks.

Panics vs Error Handling

  • One subthread questions whether contracts that abort (or “panic”) are better than silently hitting UB.
  • Pro‑panic side: failing fast near the bug with a clear message is safer and easier to debug than memory corruption.
  • Anti‑panic side: in many domains (embedded, real‑time, critical systems), crashing is unacceptable; contracts that unconditionally abort remove the caller’s ability to recover (e.g., from allocation failure).

Missing Pieces and Alternatives

  • Some lament effort on contracts while C still lacks standardized slice/span types or built‑in bounds‑safe arrays.
  • D’s long‑standing contracts and other features (CTFE, modules, safer arrays, no preprocessor) are cited as models C/C++ could have followed.
  • Static analysis and contract checking across translation units are discussed, but feasibility in a mutable, global‑state C world is seen as challenging.