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' loop soundness — 2-iteration check on while/for (Refs #177)
Rebased reduction of the original Slice C' PR. The StmtAssign
clear-on-rewrite half is dropped — that work landed in #399 with a
strictly better `is_whole_place_write` predicate (whole-place writes
clear the move; sub-place writes still apply `check_use`). This PR
keeps only the loop-soundness piece.
What lands:
- `StmtWhile` / `StmtFor`: run cond+body once, snapshot state-fields,
run cond+body a second time from the post-iter-1 state. Any move
the body didn't restore surfaces as UseAfterMove on the 2nd pass.
State is restored to the iter-1-post snapshot for post-loop
analysis (the loop may execute 0..N times — iter-1-post is the
sound choice when iter-2 doesn't add new conflicts).
- Pairs with #399's clear-on-rewrite to make legitimate re-init
loops accept: iter 1 moves and reassigns, iter 2 sees the
reassigned (cleared) state.
Three new fixtures pin the cases:
- `slice_c_prime_loop_sound.affine` — counted loop, no moves: Ok
(anti-regression against the 2-iter pass introducing false
positives).
- `slice_c_prime_loop_reinit_ok.affine` — move + immediate rebind:
Ok (the #399 × Slice C' interaction).
- `slice_c_prime_loop_move_persists.affine` — move without rebind:
Error UseAfterMove (the soundness gain).
Suite: **335/335 green** (332 prior + 3 new).
Deferred-items comment at `lib/borrow.ml:1483` updated — loop-
soundness entry removed, only Polonius and captured-linears Slice D
remain.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments