You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
[0.0.191] - 2026-07-01
Changed
Codegen type-check-impossible guards now raise CodegenInvariantError ([E699]) (#657, follow-up to #626). The #626 audit classified every return None in vera/codegen/** and vera/wasm/**; #658 converted the 104 user-actionable SILENT_SKIP sites to CodegenSkip ([E602]). This converts the genuine INVARIANT_DEFENSIVE guards — non-forwarding dispatch fall-throughs and shape guards on states the type checker has already rejected — to raise CodegenInvariantError, surfaced at the _compile_fn boundary as an [E699] "internal compiler error, please file a bug" (severity error) instead of a silent skip or a mis-attributed [E602]. 21 sites: 2 in codegen/closures.py, 19 in wasm/operators.py; pinned by tests/test_codegen_invariant_e699.py. Behaviour-preserving — the converted paths are # pragma: no cover (type-check-impossible). A closure-body invariant now propagates to _compile_fn for a single [E699] (rather than being caught in _compile_lifted_closure, which emitted [E699]and returned None so the enclosing function also got a spurious [E602] "closure skipped"); and the quantifier-predicate guard is tightened to require exactly one parameter (so a malformed multi-parameter predicate raises rather than silently using the first).
Corrected the #626 audit's PROPAGATE premise (#657). The audit assumed #658 made every codegen leaf raise, leaving the PROPAGATE if x is None: return None forwards dead. That is false for the #630[E615] string-interpolation channel: _translate_interpolated_string records failing segments and returns None, which propagates up and is dropped loudly as [E615] at the _compile_fn boundary. So translate_expr / translate_block still return Nonereachably, and forwards of them are load-bearing PROPAGATE, preserved — not removed (satisfying the issue's "preserved (still reachable)" criterion). Five operators.py sites the audit had tagged INVARIANT were in fact such forwards and are kept as return None; the inference.py defensive sites are kept as Optional-by-contract. The invariant is now documented in vera/skip.py ("Reachable None via the [E615] channel") and at every preserved forward, so a future cleanup pass can't repeat the mistake (which the test suite caught as an AssertionError in TestE615LoudInterpolationFallthrough630).