Files
AILang/examples/test_loop_binder_captured_by_lambda.ail.json
T
Brummel 39380d361d test: RED — lambda capturing a loop binder must fail ail check (loop-recur.tidy)
Milestone-close audit (architect, edd2558) surfaced a [high]
correctness defect: a (lam ...) body that references a loop binder
passes `ail check` (exit 0) then panics unreachable!() at codegen
(crates/ailang-codegen/src/lambda.rs:102) on type-correct input —
a DESIGN.md "Robustness against hallucinations" violation.

Root cause (debugger-confirmed): the Term::Lam escape guard at
crates/ailang-check/src/lib.rs:3608 inspects only mut_scope_stack;
loop binders live in `locals` (Term::Loop arm ~:3911, iter-2
design), so the mut.4-tidy MutVarCapturedByLambda-class rejection
has no loop-binder counterpart — the capture is accepted at check
and crashes codegen.

This RED commit pins the FIXED contract: the program must fail
`ail check` with code `loop-binder-captured-by-lambda` (symmetric
to mut-var-captured-by-lambda), NOT panic codegen. RED today
(left: [] vs right: ["loop-binder-captured-by-lambda"]); 6 prior
loop_recur_typecheck_pin tests still green. GREEN follows.
2026-05-18 00:08:51 +02:00

43 lines
1.4 KiB
JSON

{
"schema": "ailang/v0",
"name": "test_loop_binder_captured_by_lambda",
"imports": [],
"defs": [
{
"kind": "fn",
"name": "main",
"type": {
"k": "fn",
"params": [],
"ret": { "k": "con", "name": "Int" },
"effects": []
},
"params": [],
"doc": "loop-recur follow-on: a lambda inside a loop body that references the enclosing loop binder `acc` is rejected with loop-binder-captured-by-lambda. Loop binders are alloca-resident and lexically scoped (iter-3 reuses the mut_var_allocas registry, emptied at the lambda frame boundary); lifting them into a heap-closure env is the same deferred work as the mut-var case. Symmetric to mut-var-captured-by-lambda.",
"body": {
"t": "loop",
"binders": [
{
"name": "acc",
"type": { "k": "con", "name": "Int" },
"init": { "t": "lit", "lit": { "kind": "int", "value": 0 } }
}
],
"body": {
"t": "let",
"name": "f",
"value": {
"t": "lam",
"params": [],
"paramTypes": [],
"retType": { "k": "con", "name": "Int" },
"effects": [],
"body": { "t": "var", "name": "acc" }
},
"body": { "t": "app", "fn": { "t": "var", "name": "f" }, "args": [] }
}
}
}
]
}