On Tue, 28 May 2024, Gina P. Banyard wrote: > On Tuesday, 28 May 2024 at 15:26, Derick Rethans <der...@php.net> wrote: > > > On Mon, 27 May 2024, Ilija Tovilo wrote: > > > > > On Sun, May 26, 2024 at 11:47 PM Gina P. Banyard intern...@gpb.moe > > > wrote: > > > > > > > On Wednesday, 8 May 2024 at 14:40, Gina P. Banyard > > > > intern...@gpb.moe wrote: > > > > > > > > > I would like to formally propose my idea for exit() as a > > > > > function brought up to the list on 2024-02-24 [1] with the > > > > > following RFC: https://wiki.php.net/rfc/exit-as-function > > > > > > > > As there haven't been any comments for nearly two weeks, I'm > > > > planning on opening the vote for the RFC on Tuesday. > > > > > > Right now, I am not going to be in favour of this. Specfically > > because the Backward Incompatible Changes don't list some of the > > backward breaking changes, and no mitigations are provided. See > > below. > > > > I also don't see the benefit from doing this in the first place. > > exit/die has always meant "bail straight out", without any function > > semantics (from https://www.php.net/exit): > > > > exit — Output a message and terminate the current script > > > > exit is a language construct and it can be called without > > parentheses if no status is passed. > > > > It's not that this a particularly new or novel behaviour. > > > > I saw somewhere else in the thread that the exit construct could > > already throw a catchable exception. I consider that a bug. > > Considering the whole point of the RFC is to make it a function, I'm > not sure why saying the current exit behaviour is not new or novel > serves any purpose.
I understand that that is the point, but I don't think it's argued *why* that needs to happen. > Is catching a TypeError a bug? Is catching a ValueError a bug? Is > catching any sort of engine Error a bug? exit throwing any Exception is the bug I was referring to. > Because this is effectively what you are saying, and if this is the > case, we might as well just reverse the "Exceptions in the engine" RFC > from 2014 [1] to make all those Errors fatal errors again which bail > out immediately. This RFC makes exit() a function such that either it > exits normally, or a TypeError is thrown if you feed it nonsense, > consistently with all our type juggling semantics. > > Moreover, when exit() was changed to use an Exception internally there > were various people in favour of being able to catch it, and have it > run finally blocks (like other programming languages do) [2] It should > also be noted exit() does not just bail out and do nothing else, any > destructors will be run before the exiting, so one can still run > userland code after it has been called [3] > > > I have just checked this for Xdebug, and you're definitely right > > with that. With the removal of the ZEND_EXIT opcode, it can not now > > detect a scope/function exit now. > > > > It also breaks my "do tasks on ZEND_EXIT" with the profiler. It is > > used to always write the closing profiling footer to the files. > > Without me being able to overload thati opcode, data would not be > > complete. I even have two bugs (with tests) for this: > > > > - https://bugs.xdebug.org/68 > > - https://bugs.xdebug.org/631 > > > > Xdebug has been overloading ZEND_EXIT for nearly 20 years now. > > AFAIK Opcodes are not part of any backwards compatibility guarantees. AFAIK it isn't documented otherwise either. Just because it's not documented, doesn't mean we should remove long term existing functionality. > You could overwrite the function pointer of exit() at MINIT with a > custom implementation. I can, but overriding functions for this sort of thing is a little bit of a hack, and I prefer having an actual API. It is also a runtime feature, not a compile time (see below again). > Alternatively, you could use the zend_is_unwind_exit() engine API to > check if the exception that has been thrown is the one that > corresponds to an exit call, this would work as of PHP 8.0. > Finally, the one that makes more work for me, is to add a new observer > API that indicates an exit() and hook into that one. That seems a fairly sensible thing to add. But that only addresses my profiler use case, and not the branch/path detection use case. > > > > > This could be re-added by checking for the never return type instead. > > > > > > I can't quite see a way on how to do that? The EXIT is replaced by an > > INIT_FCALL/DO_ICALL: > > > > 4 0 E > EXT_STMT > > 1 ECHO '55' > > 5 2 EXT_STMT > > - 3 > EXIT > > - 6 4* EXT_STMT > > - 5* ECHO '675' > > - 7 6* EXT_STMT > > - 7* > RETURN null > > + 3 INIT_FCALL 'exit' > > + 4 DO_ICALL > > + 6 5 EXT_STMT > > + 6 ECHO '675' > > + 7 7 EXT_STMT > > + 8 > RETURN null > > > > > > The opcodes don't have direct access to the type mask structure as > > far as I know. > > You can access the zend_function pointer from the opcode which has > access to the type-mask info. Isn't that only during runtime, and not compile time? The branch/path detection works with the op_array, just after it has been created through compile_file. I don't see any structure in the DO_ICALL opcode that has access to this never flag. > Or, if required, the Zend/Optimizer/zend_func_infos.h file can be > amended to include exit() and die() and expose the MAY_BE_NEVER return > type. I don't think that helps either, as that is also run time? cheers, Derick