-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] Convert exit (and die) from language constructs to functions #13483
Conversation
Zend/zend_execute.c
Outdated
if (UNEXPECTED( | ||
zend_string_equals_literal_ci(Z_STR_P(key), "exit") | ||
|| zend_string_equals_literal_ci(Z_STR_P(key), "die") | ||
)) { | ||
zend_throw_unwind_exit(); | ||
return FAILURE; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we achieve similar results with by de-sugaring exit;
to a function call at the AST level? (e.g. zend_compile_const()
can replace the AST with a function call AST and delegate to zend_compile_call()
). This would remove the need for special cases at runtime, and also unify the behavior of exit;
and exit();
(wrt to disable_functions).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Special-casing exit/die constant access doesn't sound like a cleaner solution than what we have now. Keeping them in the lexer/parser also keeps BC for AST-based tools.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, and it has side effects like defined(), constant() calls etc.
We may opt to special-case only statement-level "exit" and "die" constant fetches directly (i.e. handle in zend_compile_stmt, in the branch for constants).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's actually a smarter way of doing it!
I'll see if I can implement this, as I still struggle with the compiler part.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may opt to special-case only statement-level "exit" and "die" constant fetches directly (i.e. handle in zend_compile_stmt, in the branch for constants).
I would prefer keeping parser support, as otherwise PHPStan and the likes need to adjust. I don't think there's a reason to break those. Edit: I guess lexer would be sufficient, as almost all of these tools use PHPParser, which defines its own AST. Still, I'd prefer letting the parser handle this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was about to suggest something similar, because exit;
not actually calling the function but just throwing that unwind exception probably leads to observable behavioral differences in debuggers dependent on whether the user wrote exit;
or exit();
, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should constrain ourselves with respect to phpstan etc.; there are worse BC breaks to be had.
I think the lexer, parser and opcodes are aside from any compatibilty guarantees.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ondrejmirtes has told me that this shouldn't be an issue if PHPParser still works, I'm asking @dseguy if this would affect Exakat or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@exakat will need an adaptation, at the parser level. That is not an issue.
0549f75
to
89aaa8f
Compare
Where is the RFC? Removing ability to use Please consider the possibility of adding die/exit functions without removing opcodes. |
@dstogov See zend_compile.c, the constants are turned into function calls. That said, I'm also a bit sceptical about the proposed benefits. I think an RFC, or at least a list on the mailing list explaining the rationale would be reasonable. |
The PR name contains |
Nice hack :), but it needs to be verified (constants may be used in places where calls are not allowed). |
The RFC is now live: https://wiki.php.net/rfc/exit-as-function and I have sent an email to internals. I'm still somewhat ill so I didn't manage to post it yesterday. |
a9fd352
to
04c54f3
Compare
As discussed on the list, here's an approach that converts And as discussed privately, the stub parser fails when run with a local PHP binary, because |
Good RFC! For example, if there is a PHP project that integrates HTTP Servers with SAPI non-CLI (which is the PHP standard) with HTTP Server with SAPI CLI, it would be possible to disable |
Note that the RFC prevents adding |
Yes, but is that in a future scope. That's the intention, right? |
It is a possible idea, I don't have any plans on pursuing it as I don't want to argue about the merits of it. But you could do a follow-up RFC if you wanted to! |
04c54f3
to
0b7215b
Compare
846afa3
to
1f2ca96
Compare
36a9449
to
401b78c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM overall.
@@ -83,9 +83,15 @@ function processStubFile(string $stubFile, Context $context, bool $includeOnly = | |||
} | |||
} | |||
|
|||
/* As exit() and die() are proper token/keywords an need to hack-around */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this is a grammatically correct sentence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix it in the commit where I add the NEWS/UPGRADING entry
function exit(string|int $code = 0): never {} | ||
|
||
/** @alias exit */ | ||
function die(string|int $code = 0): never {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter names seem to be incorrect.
It should be $status
, not $code
.
The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal
It is also the name already used in the manual.
Lastly, the parameter name $status
better covers what can be passed: either a status message or a status code.
While $code
would read pretty weird when passing a message:
exit(code: 'message');
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Girgias Note: I'll happily try to provide a PR to fix this, including adding a test with named parameter use, but I wanted to check first if this was an oversight or if there was a particular reason for the parameter name change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#15433 (draft as I've guestimated a patch ;-) )
Follow up on 13483 As previously reported in php#13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument.
Follow up on 13483 As previously reported in php#13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument.
Follow up on 13483 As previously reported in php#13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument.
Follow up on 13483 As previously reported in php#13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument.
Follow up on 13483 As previously reported in php#13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument.
Follow up on 13483 As previously reported in #13483 (comment): > The parameter names seem to be incorrect. > > It should be `$status`, not `$code`. > > The RFC explicitly uses that parameter name in the proposal: https://wiki.php.net/rfc/exit-as-function#proposal > > It is also the name already used in the [manual](https://www.php.net/exit). > > Lastly, the parameter name `$status` better covers what can be passed: either a status _message_ or a status _code_. > While `$code` would read pretty weird when passing a message: > ```php > exit(code: 'message'); > ``` This commit attempts to fix this. Includes adding a test for exit/die using a named argument. Co-authored-by: jrfnl <jrfnl@users.noreply.github.com>
Should the UPGRADING.INTERNALS perhaps also note here that ZEND_EXIT doesn't exist anymore? Because some extensions will now fail with the next PHP 8.4 release. For example, swoole-src The list of extensions that uses the ZEND_EXIT is not that long:
(some extensions here can probably be also archived and aren't that critical since they don't accept any PRs nor they seem to get moving anywhere) |
Ah yes it should |
This AST node is no longer used since `exit()` was made a real function in phpGH-13483.
This AST node is no longer used since `exit()` was made a real function in GH-13483.
The main motivation here is to have the same type juggling semantics as every other function in PHP.
Also, we don't need to have an opcode any more for it.
RFC: https://wiki.php.net/rfc/exit-as-function