====== PHP RFC: Treat Enum Instances as Values ====== * Version: 0.1 * Date: 2023-04-28 * Author: Garet Claborn, garet@suiteux.com * Status: Draft * First Published at: http://wiki.php.net/rfc/treat_enum_instances_as_values ===== Introduction ===== From the RFC template's opening quote, this RFC aims to be "pragmatic", "loosely typed" and cater to all camps observed in the debate (as found to date.) This RFC proposes to allow the use of enum instances as array keys in PHP. More specifically, where errors are produces in any context where an enum instance is used without ->value or ->name, the engine should instead assume ->value. This change aims to enhance the usability and consistency of enums in PHP by treating enum instances as symbols of their respective values - especially in the context of array keys. This will allow large amounts of existing code in various C-style languages to be compatible with PHP usage without affecting current projects. Further, this proposal provides potential future RFC a path to enable array key type constraints in line with present == vs === semantics and ArrayAccess, without drastic engine overhauls. ===== Proposal ===== Given that enums already exist in PHP and enum cases are mapped to either ints or strings exclusively, we propose the following changes: Enum instances should be allowed to be used as array keys without producing an error. When an enum instance is used as an array key, it should be treated as a symbol of its value. UnitEnum , not backed as an int or string, should treat value as an unsigned integer iterating from 0, more specifically modeling the relationship of enumeration (as a mathematical construct) with the natural numbers. Example: Consider the following enum and array: enum Color: int { case red = 1; case green = 2; case blue = 3; } enum WeekDays: int { case monday = 1; case tuesday = 2; case wednesday = 3; } $palette = [ 1 => 'Red', 2 => 'Green', 3 => 'Blue', ]; Currently, the following code produces an error: Color $red = Color::red; $paint = $palette[$red]; // Error With this proposal, the code above should not produce an error and should work as expected: Color $red = Color::red; $paint = $palette[$red]; // 'Red' Last on a more opinionated note; the author suggests that enum cases are userland symbols and should imply value. Just as there is no need in the following scenario: $a = 1; $b = '2'; $list = [ $a => 'some value', $b => $some_value; ]; vs $list = [ $a->value => 'some value', $b->value => $some_value; ]; ===== Backward Incompatible Changes ===== There are no backward-incompatible changes introduced by this proposal. ===== Proposed PHP Version(s) ===== Next PHP 8.x.y ===== RFC Impact ===== ==== To SAPIs ==== None ==== To Existing Extensions ==== None ==== To Opcache ==== Implementation being studied. None expected. Enums may not need some checks. ==== php.ini Defaults ==== Could be a toggle if community desired ===== Future Scope ===== While this proposal originated in a issue with wide support, referenced below, we consider strongly the negative feedback which all surrounded adding greater type mechanics to keys. Presently there are many proposals in the history of PHP regarding object keys, direct overloading of the [ ] operators and a wide arrangement of considerations around typing. We propose that many of these wishes can be addressed with much less effort if we begin at the loose typing and iteratively add stronger typing. From present knowledge, the PHP internals teams have found methods of using specific classes of objects as keys but not a road to generic objects. If enum labels ever meet this criteria in their own right, as references to enum instances, such an implementation will take precedence over this RFC. Semantics would be the same in either case, however userland glue code can enable usage patterns which inform future development by enabling this present RFC. Future RFCs are recommended to enable Day::Monday == Color::Red //true Day::Monday === Color::Red //false Which could in turn allow class MyType implements ArrayAccess //... public function offsetGet(Month $which){ //... } //... } class YourType implements ArrayAccess //... public function offsetGet(mixed $which){ //... } //... } Making the desirable $myobj = new MyType(); $yourobj = new YourType(); $x = $myobj[Color::Yellow]; // error $y = $yourobj[Color::Yellow]; // fine Such a roadmap finally enables users to user to simply use match($this) and other userland syntactic sugar to simulate object keys. This gap can be further reduced and optimized from there. ===== Proposed Voting Choices ===== A two-thirds majority is required for this proposal to be accepted. ===== Patches and Tests ===== Pending ===== Implementation ===== Author's org has committed work on this issue and having it implemented, assuming community is in favor and this is not trivial for an existing member. Any guidance from those who have worked previously with enums is appreciated. ===== References ===== A robust discussion about further pros/cons/considerations at the original issue - https://github.com/php/php-src/issues/9208 Mailing list introduction and opening RFC- https://news-web.php.net/php.internals/120117 Mailing list post-RFC discussion: TBD ===== Rejected Features ===== None to date