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:
26
examples/237-cleanup-body-restrictions.sx
Normal file
26
examples/237-cleanup-body-restrictions.sx
Normal file
@@ -0,0 +1,26 @@
|
||||
// Cleanup-body control-flow restrictions (ERR step E1.7 follow-up). A `defer`
|
||||
// or `onfail` body runs while the block/function is already exiting, so it has
|
||||
// no target to transfer control to: `raise` / `try` / `return` / `break` /
|
||||
// `continue` are all rejected inside one. The ban is transitive through nested
|
||||
// `catch` bodies and loops, but NOT through a nested closure (its own function
|
||||
// boundary). `raise` was already banned (E1.3); this adds the other four.
|
||||
// This file is expected to FAIL compilation (exit 1).
|
||||
//
|
||||
// Run: ./zig-out/bin/sx run examples/237-cleanup-body-restrictions.sx
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
E :: error { Bad }
|
||||
|
||||
g :: () -> !E { return; }
|
||||
|
||||
f :: () -> !E {
|
||||
defer { return; } // ERROR: return in defer body
|
||||
onfail { try g(); } // ERROR: try in onfail body
|
||||
defer { for 0..1: (i) { break; } } // ERROR: break in defer body (transitive through loop)
|
||||
onfail e { if e == error.Bad { continue; } } // ERROR: continue in onfail body
|
||||
try g();
|
||||
return;
|
||||
}
|
||||
|
||||
main :: () -> s32 { return 0; }
|
||||
Reference in New Issue
Block a user