ERR/E1.7: ban return/break/continue/try in defer & onfail bodies

A defer or onfail body runs while the block/function is already exiting, so it
has no target to transfer control to. `raise` was already rejected (E1.3); this
adds the rest of the locked set — `return` / `break` / `continue` / `try`.

In parseStmt, the return/break/continue/try parse sites now call a new
rejectInCleanup() helper, gated on in_onfail_body || in_defer_body (the existing
flags, whose doc-comments already scoped this follow-up). The ban is transitive
through nested catch bodies and loops, but parseLambda clears both flags for the
closure body — a closure is its own function boundary, so a `return` from a
closure created inside a cleanup body stays legal. The diagnostic names the
cleanup kind ("an `onfail`" / "a `defer`").

examples/237-cleanup-body-restrictions.sx covers the rejected forms (exit 1);
six inline parser tests cover each banned exit, the transitive-through-loop
case, the closure-boundary exception, and flag-restore after the defer.

Note: examples/213-canonical-map.sx is the user's uncommitted heterogeneous-
variadic-pack WIP (prints 40 vs expected 42); it fails on the committed parser
too, independent of this change, and is left unstaged.

Gates: zig build, zig build test (288 pass), bash tests/run_examples.sh (all
green except the unrelated 213 WIP).
This commit is contained in:
agra
2026-06-01 01:14:24 +03:00
parent 66740fa95b
commit f9dd965b69
4 changed files with 117 additions and 0 deletions

View File

@@ -0,0 +1 @@
1

View File

@@ -0,0 +1,5 @@
error: `return` is not allowed inside a `defer` body — cleanup runs while the function is already exiting, so there is nothing to transfer control to
--> /Users/agra/projects/sx/examples/237-cleanup-body-restrictions.sx:18:14
|
18 | defer { return; } // ERROR: return in defer body
| ^^^^^^