Files
AILang/design/contracts/0015-language-constraints.md
Brummel eaa52ff64f docs(contracts): honesty-prose cleanup + ratifier integrity
Second tranche of the contracts-against-code audit. Two threads, both
applied conservatively under the over-correction guards in
docs_honesty_pin.rs (the self-labelled tiebreaker in 0008 and the
Diverge-reserved anchor in 0010 are deliberate honest content and were
left untouched; design rationale that explains a present-state design
principle — semantic-locality, the reuse-as-wrapper reasons — was also
preserved).

Honesty-rule (0007): demote clear change/deletion narration to
present tense.

- 0008: drop "they were promoted from ... to ... Recorded here so";
  strip the "Iter A"/"Iter B" iteration labels (the descriptive titles
  carry the meaning); drop "(no longer a carve-out)".
- 0001: "were rewired to use ... was deleted at the same time" ->
  present tense. (The substance was already correct: `pretty.rs` holds
  only the diagnostic helpers; an audit agent had misread the line as
  "pretty.rs was deleted" — the file exists, the printer code does not.)
- 0012: drop "Per the tail-call survey of existing fixtures" and
  "Migration of existing fixtures is partial" -> present-state
  description of which corpus fixtures carry the tail marker.

Ratifier integrity: a contract that names a test which does not
ratify it is itself a form of the dishonesty this ledger forbids.

- 0014 named `bench/architect_sweeps.sh`, which sweeps honesty-anchors
  and ratifies none of the six verification mechanisms; and claim 5
  cited `tests/expected/`, which never existed (git log empty). Point
  claim 5 at the real golden mechanism (`crates/ail/tests/snapshots/`
  via `ir_snapshot.rs`) and the footer at each mechanism's actual test.
- 0015's four constraints are guaranteed by absence (no thunk/`ref`/
  `IORef` node, non-recursive `let`); the named uniqueness in-source
  tests only count RC consumes, never the constraints. State the
  by-construction guarantee and point the ratifier at `ast.rs` (the
  single source of truth for which nodes exist).
- INDEX ratifying-test column updated for both to match.

All ledger pins green (docs_honesty_pin, design_index_pin incl.
every_contract_names_a_resolvable_ratifying_test, effect_doc_honesty_pin,
carve_out_inventory); architect honesty sweep clean.

Deferred, recommend-only: 0016-method-dispatch carries no invariant
absent from 0013 (merge candidate), but a contract-file merge touches
INDEX, the retired-counter convention, and cross-refs — a structural
call left for explicit direction. Minor history phrasing in 0008's
Type::Con.name hash-shift paragraph (§"FnDef.suppress") also left.
2026-06-02 11:27:53 +02:00

2.2 KiB
Raw Permalink Blame History

Language-design constraints (binding)

Language-design constraints (binding)

The four constraints below are necessary preconditions for RC to be sound and complete without a cycle-collector backstop. The memory model relies on all four:

  1. Strict evaluation. Every Term::App (see Data model) argument is fully evaluated before the call. No laziness, no thunks. (Already true.)
  2. No recursive value bindings. (let x EXPR ...) evaluates EXPR in a scope where x is not bound. Recursion is exclusively via Term::LetRec (which binds a fn, not a value) and module-level fn defs. (Already true.)
  3. No shared mutable refs. Values are immutable once constructed. There is no ref, IORef, Mutex, or any primitive that allows a value to be mutated from a position outside its allocation. (Already true.)
  4. ADTs are acyclic by construction. Strict evaluation + no-recursive-value-bindings + no-shared-mutable-refs together guarantee that any value graph reachable from a binding is a DAG. The reference graph has no cycles. (Follows from 13.)

Laziness, recursive value bindings, shared mutable state, or any feature that creates cycles is rejected at design time unless the proposal proves the cycle is collectible by an extension (e.g. linear ownership).

These constraints are the precondition for the memory model: a sound RC implementation without a cycle-collector backstop requires the reference graph to be a DAG, which constraint 4 establishes from 13. They are also the load-bearing structural reason behind several rejections under the feature-acceptance bug-class-reintroduction discriminator (notably iterated-mutable-state reasoning).

Guaranteed by construction, not by a positive test: the AST has no thunk, ref, or IORef node, and (let x EXPR ...) binds x only in the body, never in EXPR — there is no construct that could violate constraints 13, and constraint 4 follows from them. The binding force is the design-time feature-acceptance gate, which rejects any proposal that would reintroduce one of them.