Skip to content

Implement data invariant(...) clauses per spec §2.6 / §6.2.3 (successor to #560) #686

@aallan

Description

@aallan

Problem

The spec describes invariant(...) clauses on data declarations (§2.6, §6.2.3) as a way to express constraints on constructor field values that are verified at every construction site. The current reference implementation does not support these — every documented form fails with [E130] no <DataName> bindings in scope because the slot environment for the invariant predicate is not wired up.

The previous tracking issue #560 was about the broken spec/SKILL examples that produced E130 — that was closed as COMPLETED on 2026-05-11 (presumably by removing/rewriting the failing examples). But the underlying feature remains NYI, and the spec + SKILL.md still describe it as a planned feature with stale citations to #560.

Current state

All four are now dangling — #560 is closed without an implementation.

Acceptance criteria

  1. data X { Mk(@Int) } invariant(@Int.0 > 0) parses, type-checks, and verifies — the predicate is discharged at every Mk(...) call site
  2. The slot environment for the invariant predicate has access to the bound field name (i.e., the @Int.0 in Mk(@Int)'s position)
  3. A counterexample is reported via E130 only when the predicate is genuinely violated, not because the slot environment is missing
  4. Documentation in spec/02-types.md §2.6, spec/06-contracts.md §6.2.3, and SKILL.md is updated to drop the NYI status box and point at concrete working examples
  5. Limitations-table entry in spec/06-contracts.md is removed
  6. New conformance test in tests/conformance/ covering: positive verification, negative verification with counterexample, refinement-type interaction, multiple invariant clauses

Why this isn't auto-injection

invariant(...) on data is different from auto-injected primitive obligations (tracked in #680). Auto-injection is "the compiler synthesises obligations for a / b, arr[i] etc."; invariant() is "the programmer declares a constraint on a custom data type". The two are independent features.

Dependency

May benefit from #427 (Tier 2 verification with assert/lemma hints) once that lands, but doesn't depend on it — the invariant predicate is typically Tier 1 (decidable arithmetic on bound fields).

Provenance

Surfaced during the 2026-05-19 v0.0.156 release doc sweep when noticing that 4 references to #560 in SKILL.md + spec/* were dangling against a closed issue. Filing as the successor to #560 with explicit acceptance criteria so the implementation work has a clear target.

Metadata

Metadata

Assignees

No one assigned

    Labels

    blockedCannot be addressed until a dependency lands; see Relationships panel

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions