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
feat(borrow): CORE-01 Slice C' (#177 pt3) — loop soundness via 2-iteration + StmtAssign clear-on-rewrite
Closes the loop-soundness item documented at lib/borrow.ml's "Still
deferred" comment. Two interlocked changes:
1. StmtAssign clear-on-rewrite (precondition for #2).
Pre-fix, [check_use] on the LHS of every assignment rejected
`x = …` when `x` had a prior move record — even though the
assignment is precisely what restores `x` to a fresh value. That
made legitimate re-init patterns impossible (`drop_int(x);
x = new_value;` in a loop body), and it made the 2-iteration
loop check unable to converge on any such loop.
Now [StmtAssign] (a) checks only for an exclusive-borrow
conflict on the LHS (not for a move), and (b) clears every
move record overlapping the LHS place after the assignment
completes.
2. StmtWhile/StmtFor 2-iteration body pass.
The body runs once; then state-fields snapshot; then cond+body
run again from the post-iter-1 state. Any move the body did
not restore via reassignment surfaces as UseAfterMove on the
second pass — that is the multi-iter soundness gain. After
both passes, state is restored to the iter-1-post snapshot so
any analysis past the loop sees a single iteration's worth of
state (loops may execute 0..N times; iter-1-post is the sound
choice when iter-2 doesn't add new conflicts).
Tests (+3, all green):
- slice_c_prime_loop_sound — counted loop converges, no false +ve
- slice_c_prime_loop_reinit_ok — drop-then-reassign in body OK
- slice_c_prime_loop_move_persists — anti-regression: move with
no rebind raises UseAfterMove on the iter-2 pass
Gate: 327 → 330 tests, 0 failures under `dune runtest --force`.
Refs #177, CORE-01 pt3 (Slice C').
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments