Skip to content
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

Implement enums #6489

Closed
wants to merge 1 commit into from
Closed

Implement enums #6489

wants to merge 1 commit into from

Conversation

iluuu1994
Copy link
Member

@iluuu1994 iluuu1994 commented Dec 4, 2020

@carusogabriel carusogabriel added this to the PHP 8.1 milestone Dec 4, 2020
Zend/tests/enum/019.phpt Outdated Show resolved Hide resolved
Zend/tests/enum/011.phpt Outdated Show resolved Hide resolved
@stof
Copy link
Contributor

stof commented Dec 5, 2020

shouldn't this also add a enum_exists function or is this covered by class_exists ?

@TysonAndre
Copy link
Contributor

  • probably need to update autoloading to autoload NS\X instead of NS\X::Y and add a test, e.g. in calls to unserialize()
  • newInstanceWithoutConstructor may also be an issue

Copy link
Contributor

@TysonAndre TysonAndre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The overall plan seems reasonable, I had some minor comments/questions about the implementation

ext/standard/var.c Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/tests/enum/025.phpt Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_enum.c Outdated Show resolved Hide resolved
ext/standard/var.c Outdated Show resolved Hide resolved
Zend/tests/enum/scalar-from-invalid-string.phpt Outdated Show resolved Hide resolved
Zend/tests/enum/scalar-from-invalid-int.phpt Outdated Show resolved Hide resolved
Zend/zend_language_parser.y Outdated Show resolved Hide resolved
Zend/zend_enum.c Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_enum.c Outdated Show resolved Hide resolved
Zend/zend_builtin_functions.c Outdated Show resolved Hide resolved
Zend/zend_builtin_functions.c Outdated Show resolved Hide resolved
@iluuu1994
Copy link
Member Author

@TysonAndre As always, thanks for the review! We're almost feature-complete but there's definitely some cleaning up to do 🙂

Zend/zend_interfaces.stub.php Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
iluuu1994 added a commit to iluuu1994/php-src that referenced this pull request Dec 23, 2020
RFC: https://wiki.php.net/rfc/enumerations

Co-authored-by: Larry Garfield <larry@garfieldtech.com>

Closes phpGH-6489.
ext/reflection/php_reflection.c Outdated Show resolved Hide resolved
ext/reflection/tests/ReflectionEnum_getCase.phpt Outdated Show resolved Hide resolved
ext/reflection/php_reflection.c Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
Zend/zend.h Outdated Show resolved Hide resolved
Zend/zend.h Outdated Show resolved Hide resolved
Zend/zend_builtin_functions.stub.php Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_compile.h Outdated Show resolved Hide resolved
Zend/zend_default_classes.c Outdated Show resolved Hide resolved
ext/reflection/tests/ReflectionEnum_hasPrimitiveType.phpt Outdated Show resolved Hide resolved
ext/standard/var_unserializer.re Show resolved Hide resolved
ext/standard/var_unserializer.re Outdated Show resolved Hide resolved
ext/standard/var.c Outdated Show resolved Hide resolved
Zend/zend_compile.c Outdated Show resolved Hide resolved
Zend/zend_ast.c Outdated Show resolved Hide resolved
Zend/zend_enum.c Outdated Show resolved Hide resolved
Zend/zend_compile.h Outdated Show resolved Hide resolved
iluuu1994 added a commit to iluuu1994/php-src that referenced this pull request Feb 28, 2021
RFC: https://wiki.php.net/rfc/enumerations

Co-authored-by: Larry Garfield <larry@garfieldtech.com>

Closes phpGH-6489.
@iluuu1994 iluuu1994 force-pushed the enums branch 2 times, most recently from 3f62a18 to 3389625 Compare March 1, 2021 23:41
@nikic
Copy link
Member

nikic commented Mar 5, 2021

This looks good apart from the questions re reflection, as well as broken persist / file cache. I'm not sure how to address that part yet.

Zend/zend_language_scanner.l Outdated Show resolved Hide resolved
Copy link
Member

@dstogov dstogov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see big problems. See my minor comments.

ext/reflection/php_reflection.c Outdated Show resolved Hide resolved
ext/reflection/php_reflection.c Outdated Show resolved Hide resolved
Zend/zend_compile.h Outdated Show resolved Hide resolved
Zend/zend_inheritance.c Outdated Show resolved Hide resolved
if (ce->ce_flags & ZEND_ACC_ENUM) {
/* Only register builtin enum methods during inheritance to avoid persisting them in
* opcache. */
zend_enum_register_funcs(ce);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work with inheritance cache? It's going to persist them anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they will be persistent in the inheritance cache. Persistence of internal methods is already supported for preloading. The important part is that a) this doesn't happen on Windows (caching for that case is disabled above) and is not persisted in file cache (which is not used for inheritance cache).

// FIXME: This causes constant objects to leak
if (!(obj->ce->ce_flags & ZEND_ACC_ENUM)) {
GC_ADDREF(obj);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment is unclear. Is it outdated or something still has to be fixed? May be handle this in enum::free_obj() handler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that currently we only destroy constants and class constants after freeing the object store, but now constants can contain objects, so we get a leak report. This requires some small changes to shutdown order. I have a patch for this already and plan to apply it afterwards.

@dstogov

This comment has been minimized.

iluuu1994 added a commit to iluuu1994/php-src that referenced this pull request Mar 17, 2021
RFC: https://wiki.php.net/rfc/enumerations

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>

Closes phpGH-6489.
RFC: https://wiki.php.net/rfc/enumerations

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>

Closes phpGH-6489.
@TysonAndre
Copy link
Contributor

What's the intended behavior of define()? As this was a large RFC documentation and implementation I'd overlooked it and assumed it would work, but the tests and rfc document don't mention anything about define( that I saw skimming over them again.

I believe it'd be reasonable and non-controversial for define() to allow anything that const foo = expr; would allow, i.e. to allow enum objects in array keys and as top-level values, e.g. this was probably just overlooked

Ideally, Zend/zend_builtin_functions.c would be changed to "cannot be/contain an object that is not an enum" or something along those lines

php > enum X: string { case FOO='bar'; }
php > const foo = X::FOO;  // this works
php > var_dump(foo);
enum(X::FOO)
php > define('foo2', X::FOO);  // this throws a TypeError

Warning: Uncaught TypeError: define(): Argument #2 ($value) cannot be an object, X given in php shell code:1
Stack trace:
#0 php shell code(1): define('foo2', Object(X))
#1 {main}
  thrown in php shell code on line 1
php > define('foo3', [X::FOO]);

Warning: Uncaught TypeError: define(): Argument #2 ($value) cannot be an object, X given in php shell code:1
Stack trace:
#0 php shell code(1): define('foo3', Array)
#1 {main}
  thrown in php shell code on line 1

@iluuu1994
Copy link
Member Author

Ideally, Zend/zend_builtin_functions.c would be changed to "cannot be/contain an object that is not an enum" or something along those lines

Is there any good reason to not just allow objects in general? Given the general direction of PHP to allow objects in constant expressions.

TysonAndre added a commit to TysonAndre/php-src that referenced this pull request May 14, 2021
Because php supports doc comments on class constants, I believe it would also
make sense to support them on enum cases.

I don't have strong opinions about whether attributes should be moved to be the
last element or whether the doc comment should go after the attribute,
but the ast will likely change again before php 8.1 is stable.
So far, all attributes are the last ast child node.

I didn't notice that doc comments weren't implemented due to
php#6489 being a large change.

https://wiki.php.net/rfc/enumerations
did not mention whether or not doc comments were meant to be supported
TysonAndre added a commit that referenced this pull request May 14, 2021
Because php supports doc comments on class constants, I believe it would also
make sense to support them on enum cases.

I don't have strong opinions about whether attributes should be moved to be the
last element or whether the doc comment should go after the attribute,
but the ast will likely change again before php 8.1 is stable.
So far, all attributes are the last ast child node.

I didn't notice that doc comments weren't implemented due to
#6489 being a large change.

https://wiki.php.net/rfc/enumerations
did not mention whether or not doc comments were meant to be supported
@TysonAndre
Copy link
Contributor

Is there any good reason to not just allow objects in general? Given the general direction of PHP to allow objects in constant expressions.

The former would be less controversial due to very likely being an oversight - and the workaround of eval('const MY_CONST = ' . var_export(EnumClass::ENUM_CASE, true)) would be worse.

The latter seems more controversial, and many would be opposed to the shift it'd allow for const to contain data that isn't actually constant (e.g. if reading or reviewing code) - the exact direction of that RFC already changed

  • (i.e. whether one would want const to mean the object and its properties won't change, or just that the object handle won't change)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants