Skip to content

fix(tla): compiled LET action clause stages helper-hidden primes - #192

Merged
zoratu merged 1 commit into
mainfrom
fix/compiled-let-with-primes
Jul 20, 2026
Merged

fix(tla): compiled LET action clause stages helper-hidden primes#192
zoratu merged 1 commit into
mainfrom
fix/compiled-let-with-primes

Conversation

@zoratu

@zoratu zoratu commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Problem

compile_action_clause_text routed a LET ... IN <body> action clause through compile_let_with_primes (which compiles the body conjuncts as action clauses so each can stage a prime) only when the LET text contained a literal '. That missed a prime hidden behind a helper call:

Act == \E i \in {1,2,3} : LET x == i + 10 IN Send(x)   \* no literal ' here
Send(m) == msg' = m                                     \* prime is in the helper

Without a visible ' the clause fell through to a boolean Guard, which evaluates the helper in value context and discards its primed assignment → the action produced 0 successors. This is exactly Paxos / SimplifiedFastPaxos PaxosAccept, previously worked around in #175 via an interpreted fallback on the empty compiled result.

Fix

Drop the && trimmed.contains('\'') condition so every LET action clause routes through compile_let_with_primes. Shapes it can't compile (e.g. a CASE-of-actions body) still return None and fall to the interpreted LetWithPrimes path; a pure value LET compiles its body to boolean Guard clauses as before. The change only adds correct prime staging — it never removes a working path.

The #175 interpreted fallback is retained as harmless defense-in-depth but is now dead for the LET case (the compiled path is correct on its own, verified with the fallback neutered).

Gate

  • scripts/diff_tlc.sh 21/21 — adds let_hidden_prime regression spec (helper-hidden-prime LET == TLC=4)
  • Paxos / SimplifiedFastPaxos still 1,207 distinct == TLC (with symmetry)
  • cargo test --release 0-fail, modulo the known load-timing-flaky prop_pause_visibility checkpoint proptest (passes 5/5 in isolation; unrelated to TLA+ eval)

…piledLetWithPrimes)

`compile_action_clause_text` routed a `LET ... IN <body>` action clause
through `compile_let_with_primes` (which compiles the body conjuncts as
action clauses, so each can stage a prime) only when the LET text
contained a literal `'`. That missed a prime hidden behind a helper call:

    LET M == ... IN SendMessage(m)      \* no literal ' in the LET text
    SendMessage(m) == messages' = ...   \* prime is in the helper

Without a visible `'` the clause fell through to a boolean `Guard`, which
evaluates the helper in value context and discards its primed assignment,
so the action produced 0 successors. This is exactly Paxos /
SimplifiedFastPaxos `PaxosAccept`, previously worked around in #175 via an
interpreted fallback on the empty compiled result.

Drop the `&& trimmed.contains('\'')` condition so every `LET` action
clause routes through `compile_let_with_primes`. Shapes it can't compile
(e.g. a `CASE`-of-actions body) still return None and fall to the
interpreted `LetWithPrimes` path, and a pure value LET compiles its body
to boolean `Guard` clauses as before — so the change only ADDS correct
prime staging, never removes a working path.

The #175 interpreted fallback (empty-compiled-result -> interpreted) is
retained as harmless defense-in-depth; it is now dead for the LET case
(the compiled path is correct on its own, verified in isolation).

Gate: diff_tlc 21/21 (adds `let_hidden_prime` regression spec: a
helper-hidden-prime LET == TLC=4); Paxos/SimplifiedFastPaxos still 1,207
distinct == TLC; cargo test 0-fail (modulo the known load-timing-flaky
`prop_pause_visibility` checkpoint proptest, which passes 5/5 in
isolation and is unrelated to TLA+ eval).
@zoratu
zoratu merged commit 2a5c3fc into main Jul 20, 2026
6 checks passed
@zoratu
zoratu deleted the fix/compiled-let-with-primes branch July 20, 2026 08:36
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