A closure literal declared inside a `defer` body segfaulted the compiler. Root cause: lowerLambda never opened its own `func_defer_base` window. Every other function-lowering entry (lowerFunction / monomorphizeFunction / monomorphizePackFn) saves func_defer_base, sets it to defer_stack.items.len, and restores it — lowerLambda didn't. So a lambda's `return` drained the ENCLOSING function's defers; when the defer body itself declared the lambda, draining re-lowered the lambda, which returned, which drained again → infinite recursion → stack-overflow SIGSEGV (the failable variant surfaced one frame out, in expandCallDefaults→lookupFn reading a clobbered scope). Fix: lowerLambda now saves func_defer_base + the defer_stack length, sets the base to the current length (a fresh window), and restores both on exit — so a lambda's `return` drains only its own defers. Regression: examples/0310-closures-closure-literal-in-defer.sx — a closure declared and called inside a `defer`; verifies `body` then `defer closure: 42` at scope exit (exit 0). Issue 0073 marked RESOLVED; repro promoted from issues/0073-*.sx. zig build, zig build test, tests/run_examples.sh (358/0) all green.
23 lines
712 B
Plaintext
23 lines
712 B
Plaintext
// Closure literal declared (and used) inside a `defer` body.
|
|
//
|
|
// Regression (issue 0073): this used to segfault lowering. A lambda inherited
|
|
// the enclosing function's `func_defer_base`, so the lambda's `return` re-drained
|
|
// the enclosing function's defers — and when the defer body itself declared the
|
|
// lambda, that re-lowered the lambda forever (infinite recursion). A lambda now
|
|
// opens its own defer window (like every other function-lowering entry).
|
|
|
|
#import "modules/std.sx";
|
|
|
|
run :: () {
|
|
defer {
|
|
cb := (n: s32) -> s32 { return n * 2; };
|
|
print("defer closure: {}\n", cb(21)); // 42, at scope exit
|
|
}
|
|
print("body\n");
|
|
}
|
|
|
|
main :: () -> s32 {
|
|
run();
|
|
return 0;
|
|
}
|