-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Proposal: Allow reserved keywords in more element declaration names(class, function, etc) #7465
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
base: master
Are you sure you want to change the base?
Conversation
This proposes to allow certain reserved keywords to be allowed as identifiers in the following places (in PHP 8.2): - Global function declarations - Global constant declarations - Named class declarations - Trait declarations - Interface declarations - Enum declarations (They were already allowed in class constant declarations, method declarations, etc.) For example, if an application was using `Match` as a class/function name prior to php 8.0, this declaration would have started being a syntax error in PHP 8.0. But with this PR, it would be possible to create element names using those keywords, or instantiate it or use to it as `\Match` instead of `Match`, thanks to https://wiki.php.net/rfc/namespaced_names_as_token having already been merged in php 8.0. - (otherwise, workarounds such as class_alias would have been required to use those identifiers as a class name, for example) This aims to reduce the backwards compatibility impact of new reserved keyword additions in new/recent PHP versions. Using keywords that can already be types (e.g. static, int, float, never) continues to be a fatal error in class names. ``` // reserved_non_modifiers: INCLUDE | INCLUDE_ONCE | EVAL | REQUIRE | REQUIRE_ONCE | OR | XOR | AND | INSTANCEOF | NEW | CLONE | EXIT | IF | ELSEIF | ELSE | ENDIF | ECHO | DO | WHILE | ENDWHILE | FOR | ENDFOR | FOREACH | ENDFOREACH | DECLARE | ENDDECLARE | AS | TRY | CATCH | FINALLY | THROW | USE | INSTEADOF | GLOBAL | VAR | UNSET | ISSET | EMPTY | CONTINUE | GOTO | FUNCTION | CONST | RETURN | PRINT | YIELD | LIST | SWITCH | ENDSWITCH | CASE | DEFAULT | BREAK | ARRAY | CALLABLE | EXTENDS | IMPLEMENTS | NAMESPACE | TRAIT | INTERFACE | CLASS | __CLASS__ | __TRAIT__ | __FUNCTION__ | __METHOD__ | __LINE__ | __FILE__ | __DIR__ | __NAMESPACE__ | FN | MATCH | ENUM // semi_reserved: | STATIC | ABSTRACT | FINAL | PRIVATE | PROTECTED | PUBLIC | READONLY ``` Alternatives Considered ----------------------- 1. One possibility was to instead only allow newly introduced keywords since some arbitrary php version (e.g. 7.0). This was rejected because decades from now, the choice of which keywords are forbidden would seem arbitrary and hard to remember. 2. Another possibility would be to allow fully qualified names in these declarations. (e.g. `class \Match`). This was rejected since allowing code in namespaces to declare elements in different namespaces was much more drastic than the approach taken here.
This also affects class_alias
@@ -9,7 +9,10 @@ class Obj | |||
function return(){} // valid | |||
} | |||
|
|||
function echo(){} // not valid | |||
function echo(){print("test\n");} // valid | |||
\echo(); |
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.
this seems quite confusing to me: https://3v4l.org/ksZdk, global declaration of echo
function should not be allowed even if it is not a real function
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.
Yeah, I think we should not allow declaring functions for keywords that can be used in a function-like way. Basically, if you have function kw() {}
and writing kw();
causes a compile error, that's okay. However, if you have function kw() {}
and writing kw();
compiles but will do something other than calling the function kw()
, then I think we should prevent the declaration.
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.
That seems easier to remember than using a cut-off date. For global functions, that would be:
INCLUDE | INCLUDE_ONCE | EVAL | REQUIRE | REQUIRE_ONCE | OR | XOR | AND
| INSTANCEOF | NEW new ('expression')
is allowed | CLONE | EXIT | IF | ELSEIF | ELSE | ENDIF | ECHO | DO | WHILE | ENDWHILE
| FOR | ENDFOR | FOREACH | ENDFOREACH | DECLARE | ENDDECLARE | AS | TRY | CATCH (requires {}) | FINALLY
| THROW | USE | INSTEADOF | GLOBAL | VAR | UNSET | ISSET | EMPTY | CONTINUE (continue (2);) | GOTO
| FUNCTION | CONST | RETURN | PRINT | YIELD | LIST | SWITCH | ENDSWITCH | CASE | DEFAULT | BREAK (break (2);)
| ARRAY | CALLABLE | EXTENDS | IMPLEMENTS | NAMESPACE | TRAIT | INTERFACE | CLASS
| __CLASS__
| __TRAIT__
| __FUNCTION__
| __METHOD__
| __LINE__
| __FILE__
| __DIR__
| __NAMESPACE__
| FN (\fn() => expr,
confusing in array key) | MATCH (requires {}) | ENUM (already allowed through tokenizer workaround)
// semi_reserved:
| STATIC | ABSTRACT | FINAL | PRIVATE | PROTECTED | PUBLIC | READONLY (also see other PR)
This proposes to allow certain reserved keywords to be allowed as identifiers
in the following places (in PHP 8.2):
(They were already allowed in class constant declarations, method declarations,
etc.)
For example, if an application was using
Match
as a class/function nameprior to php 8.0, this declaration would have started being a syntax error
in PHP 8.0 due to https://wiki.php.net/rfc/match_expression_v2 .
But with this PR, it would be possible to create element names using those
keywords, or instantiate it or use to it as
\Match
instead ofMatch
,thanks to https://wiki.php.net/rfc/namespaced_names_as_token
having already been merged in php 8.0.
Motivation
to use those symbols even if they were declared until php 8.0. It is now practical.
identifiers such as
Match
as a class/function name when upgrading to php 8.0, for example)it would be useful to be able to use reserved keywords as names, e.g. to integrate with applications written in other programming languages and to easily serialize/unserialize data using those symbols
This aims to reduce the backwards compatibility impact of new reserved keyword
additions in new/recent PHP versions, both to aid users in migrating
and reducing objections to new syntax proposals that depend on new keywords.
https://wiki.php.net/rfc/namespaced_names_as_token#future_scope turns out to have mentioned this in the Future Scope
Details
Using keywords that can already be types (e.g. static, int, float, never)
continues to be a fatal error in class names.
The following keywords would be allowed
Additionally, forbid using
callable
as a class name because it is a type hint.Previously, it would be a ParseError unless using
class_alias
.This is already done for
never
,iterable
,mixed
, etc., so I assume this was an oversight?Alternatives Considered
One possibility was to instead only allow newly introduced keywords
since some arbitrary php version (e.g. 7.0) but continue forbidding old keywords introduced prior to that version.
This was rejected because decades from now, the choice of which keywords
are forbidden would seem arbitrary and hard to remember.
Another possibility would be to allow fully qualified names in these declarations.
(e.g.
class \Match
).This was rejected since allowing code in namespaces to declare elements
in different namespaces was much more drastic than needed (and break current conventions) - the approach taken in this PR would be sufficient.