Skip to content

route a call through a loop variable to the loop's storage slot - #618

Merged
kacy merged 1 commit into
mainfrom
loop-var-fn-call
Jul 29, 2026
Merged

route a call through a loop variable to the loop's storage slot#618
kacy merged 1 commit into
mainfrom
loop-var-fn-call

Conversation

@kacy

@kacy kacy commented Jul 29, 2026

Copy link
Copy Markdown
Owner

summary

the loop-variable slot fix gave for f in fns: its own storage
(__loopvar_0_f), but a call through the variable still emitted call r f.
the consumer resolves a non-function callee by variable name, found no f,
and fell through to the runtime's unresolved-function stub, so a program that
compiled cleanly died at runtime. indexing (fns[i](x)) always worked, which
is why the gap survived: nothing in the corpus called through a loop variable.

the fix is one interception in the static-call path: a bare-identifier callee
that is not a declared function consults the same loop-slot mapping that loads
and stores already use. a declared function keeps its direct call even if a
loop variable of the same name is live, so nothing existing changes shape.

what was tested

new regression case: the plain loop call, nested loops with two live fn
variables at once, rebinding the loop variable's name after the loop, and a
mixed pair of List[fn(Int) -> Int] and List[fn(Int) -> String]. verified
identical under green default and PITH_GREEN=0, and valgrind-clean with the
struct freelist disabled.

full battery: make test both backends, make bootstrap-verify, both corpora,
make memcheck, make leak-check. seed refreshed last and the driver rebuilt
from the committed seed alone.

giving a for loop variable its own slot fixed the over-release and the
clobbering, but a call through that variable still named the source variable:
`for f in fns:` stored into __loopvar_0_f while `f(x)` emitted `call r f`. the
consumer resolves a non-function callee by variable name, found no `f`, and
fell through to the unresolved-function stub — a compile-clean program that
died at runtime with "call to a function the compiler could not resolve".
indexing the list worked all along, which is how it hid.

the callee resolution now consults the loop-slot mapping the loads and stores
already use, only for a bare identifier that is not a declared function — so a
plain function call cannot be captured by a loop variable that happens not to
shadow it, and everything else is unchanged.

the case covers the plain loop call, nested loops with two live fn variables,
rebinding the name after the loop, and a mixed-type pair of fn lists.
@kacy
kacy merged commit b169078 into main Jul 29, 2026
2 checks passed
@kacy
kacy deleted the loop-var-fn-call branch July 29, 2026 11:29
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