WIP: Zend: add native defer keyword (parser/compiler + VM opcodes)#20786
WIP: Zend: add native defer keyword (parser/compiler + VM opcodes)#20786khaledalam wants to merge 5 commits into
Conversation
- Add T_DEFER token and ZEND_AST_DEFER AST node - Compile defer blocks by emitting a skip JMP + trailing JMP back - Add DEFER_PUSH/DEFER_RUN VM handlers using per-call defer_stack - Run defers before explicit/implicit returns (LIFO) - Add initial PHPT tests (basic/LIFO/early return/vars); exception unwind not yet supported
|
Hi @khaledalam. I'm skeptical of this approach. It effectively mirrors FWIU Zig executes Also note there are two recent, competing RFCs that are similar. https://wiki.php.net/rfc/optin_block_scoping |
|
https://packagist.org/packages/wikimedia/scoped-callback may solve what you are looking for, runs a function via a variable destructor when the variable goes out of scope |
Thanks @iluuu1994 totally fair points. I didn’t fully account for the optimizer complexity until I started implementing this and ran into test regressions, and I also underestimated the real complexity/semantics in loops (accumulating defers across iterations). |
Thanks @DanielEScherzer, good pointer. I actually built something very similar in userland (scoped-callback style). My motivation for exploring this in core is mainly language-level ergonomics and avoiding overhead in hot paths, but given the feedback here I'll re-evaluate the direction and how it overlaps with existing solutions/RFCs. |
|
I just recently used a defer in Swift and thought to myself, "this would be nice in PHP!" Would love to see this happen! One thing I thought was, we could possibly reuse the
Would operate as though the current scope was in a Either way, I'm excited about the prospect of this! |
|
For some more prior art, I use https://github.com/php-defer/php-defer/blob/5.0/src/functions.inc.php which is kinda Go-like, most typically for doing a DB rollback "if the current scope didn't successfully commit", essentially. One thing to note, Xdebug causes this approach to fail due to https://bugs.xdebug.org/view.php?id=2222, it holds onto references in stack traces longer than it should so it breaks the predictability of destructors being called at the end of a function scope when its last variable ref goes away. |
Inspired by Zig's "defer", it schedules a block to run when the current function exits (return, exception, or natural end), executed in LIFO order, aimed at safer cleanup without repetitive try/finally scaffolding.