Description
While researching within the PHP source codebase on Enums, I encountered several inconsistencies for which I've been unable to discover the reason.
Magic Method Errors
Enums cannot implement any magic methods, besides __call, __callStatic and __invoke. Implementing others will give you an E_COMPILE_ERROR of Enum may not include %s. But, because of how __sleep, __wakeup and __set_state are handled, implementing them gives you an E_COMPILE_ERROR of Enum may not include magic method %s. While I don't entirely understand why there's a different code path for those magic methods, I believe the difference is an internal implementation issue; therefore, the error messages for the end user should be consistent.
I'm pretty confident the solution for this would be to update the error message thrown by ZEND_ENUM_DISALLOW_MAGIC_METHOD, as the second error message that mentions magic methods is nicer and more descriptive. I do not know the impact of this, as I'm unsure where error messages fall when it comes to backwards compatibility.
I am happy to test and PR myself.
Banned Interfaces
Enums can implement any interface, except Serializable, which I suspect is down to the fact that this interface cannot be implemented without also implementing some of the magic methods that enum cannot have. There is a specific code path for this that throws an error.
I believe that the Stringable interface falls into this same category. Since this interface has a single method, __toString, it cannot be implemented without using one of the banned magic methods.
I think the best solution would be to add a specific check for Stringable within zend_verify_enum_interfaces. However, I'm unsure of the side effects as Stringable is both an implementable and an implicit interface.
I am happy to test and PR myself.
Description
While researching within the PHP source codebase on Enums, I encountered several inconsistencies for which I've been unable to discover the reason.
Magic Method Errors
Enums cannot implement any magic methods, besides
__call,__callStaticand__invoke. Implementing others will give you anE_COMPILE_ERRORofEnum may not include %s. But, because of how__sleep,__wakeupand__set_stateare handled, implementing them gives you anE_COMPILE_ERRORofEnum may not include magic method %s. While I don't entirely understand why there's a different code path for those magic methods, I believe the difference is an internal implementation issue; therefore, the error messages for the end user should be consistent.I'm pretty confident the solution for this would be to update the error message thrown by
ZEND_ENUM_DISALLOW_MAGIC_METHOD, as the second error message that mentions magic methods is nicer and more descriptive. I do not know the impact of this, as I'm unsure where error messages fall when it comes to backwards compatibility.I am happy to test and PR myself.
Banned Interfaces
Enums can implement any interface, except
Serializable, which I suspect is down to the fact that this interface cannot be implemented without also implementing some of the magic methods that enum cannot have. There is a specific code path for this that throws an error.I believe that the
Stringableinterface falls into this same category. Since this interface has a single method,__toString, it cannot be implemented without using one of the banned magic methods.I think the best solution would be to add a specific check for
Stringablewithinzend_verify_enum_interfaces. However, I'm unsure of the side effects asStringableis both an implementable and an implicit interface.I am happy to test and PR myself.