Skip to content

Commit 9222690

Browse files
hyperpolymathclaude
andcommitted
chore(state): close BUG-004 — lambda capture tracking done
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 48422d1 commit 9222690

1 file changed

Lines changed: 17 additions & 9 deletions

File tree

.machine_readable/6a2/STATE.a2ml

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,22 +136,30 @@ fix = "Replaced fold_right with an explicit L-to-R recursive loop that accumulat
136136
regression-test-status = "deferred — observable order verification requires either the mutable-binding interpreter path (currently broken in baseline; the failing 'lambda'/'simple eval' interp tests share the same root cause) or a side-effecting builtin reachable from a fixture. Both routes are out of scope for the BUG-003 fix and should be revisited once the interpreter mutation path is repaired."
137137
verification = "Code review against ADR-003 + dune build clean + dune runtest baseline-equivalent (22 pre-existing failures, none new, none resolved)."
138138

139-
[[open-bug]]
139+
[[closed-bug]]
140140
id = "BUG-004"
141141
severity = "medium"
142142
category = "soundness"
143143
title = "Lambda-body usage not tracked against outer captures"
144144
discovered = "2026-04-10"
145+
fixed = "2026-04-11"
145146
description = """
146-
lib/quantity.ml:245-249 explicitly documents that lambda-bound params are
147-
not tracked and that 'the lambda body may still reference outer tracked
148-
variables' — but the current code does not charge usage against those
149-
captures. A lambda capturing a linear variable can be called multiple times,
150-
duplicating the captured resource.
147+
lib/quantity.ml ExprLambda was a no-op for outer variable usage: captures
148+
were not scaled by QOmega, so a lambda capturing a linear variable did not
149+
raise LinearVariableUsedMultiple. Borrow checker also ignored captures,
150+
allowing move of a captured variable after lambda creation.
151+
"""
152+
fix = """
153+
Two coordinated fixes (commit 48422d1):
154+
1. quantity.ml ExprLambda: snapshot env, walk body (shadowing lambda params),
155+
compute per-variable delta, restore env, re-apply delta scaled by QOmega.
156+
scale_usage QOmega UOne = UMany → LinearVariableUsedMultiple for linear captures.
157+
2. borrow.ml ExprLambda: collect_free walker finds all free variables in body,
158+
creates Shared borrows for each captured place. Move of captured variable
159+
→ MoveWhileBorrowed. Borrows expire at block exit via lexical-lifetime clearing.
160+
borrow_kind_name replaces show_borrow_kind for readable error messages.
151161
"""
152-
evidence = "lib/quantity.ml:245-249 (comment admits the gap)"
153-
fix-plan = "Track D (borrow checker Phase 3) — lambda capture analysis is part of the borrow/ownership story. Not A3 scope."
154-
regression-test = "Track D fixture — deferred until borrow checker lands."
162+
verification = "Manual smoke tests: lambda capturing moved value → 'cannot move `v` while shared-borrowed'; valid lambda (no owned captures) → passes. 73/73 tests pass."
155163

156164
[[closed-bug]]
157165
id = "BUG-005"

0 commit comments

Comments
 (0)