Fwd: Re[2]: [PHP-DEV] PHP 8.1 enum const expr essions problem

From: Date: Fri, 30 Jul 2021 00:01:00 +0000
Subject: Fwd: Re[2]: [PHP-DEV] PHP 8.1 enum const expr essions problem
Groups: php.internals 
Request: Send a blank email to internals+get-115609@lists.php.net to get a copy of this message
>> >> Hello internals! I apologize if such a discussion has already taken >> place, but I didn't find anything like it. >>   >> When working with enums, I ran into problems that are currently not >> resolved. In some cases, enumerations require self references and >> constant arithmetic expressions: >>   >> enum Example: int >> { >>     case A = 0b0001; >>     case B = 0b0010; >>     case C = 0b0100; >>   >>     public const EXAMPLE_MASK = self::A | self::B; // << Invalid expression >>     public const EXAMPLE_MASK2 = self::A->value | self::B->value; // << Same >> } >>   >> Similar examples can be taken in the existing PHP code, for example, >> for attributes (Attribute::TARGET_ALL) which is a binary mask for >> existing «targets». Thus, if targets for attributes were implemented >> through enumerations, and not through constants, then it would be >> impossible to implement such functionality. >>   >> In addition, enumeration values are not part of constant expressions, >> so implementation through "Example::A->value" is also not available. >>   >> Can you please tell me, maybe there have already been some discussions >> of this problem? And if not, then maybe we should solve this problem >> before PHP 8.1 release? Since it seems to me that the lack of such >> functionality is quite critical. >What you're describing is enum sets. That is, a value that is itself a union of two enum >values. Those are not supported at this time. It's actually a bit tricky to do, since >internally enum cases are not a bit value but an actual full PHP object. So self::A | self::B would >be trying to bitwise-OR two objects, which is of course meaningless. > >The second doesn't work because technically self::A is an object, not a constant, so it >cannot be used in a constant expression. The only dynamicness added in 8.1 was for "new" >expressions in initializers. The objects don't exist at compile time so they cannot be reduced >down to a constant value pre-runtime. > >I agree the current situation is suboptimal. I don't think anyone is opposed to enum sets, >but they're a non-trivial amount of work to do and we haven't figured out how to do them >yet. There's no simple way to address it as as bug, so any larger effort will have to wait for >8.2. > >--Larry Garfield > >-- >PHP Internals - PHP Runtime Development Mailing List >To unsubscribe, visit: https://www.php.net/unsub.php Yes, I saw this short description in your RFC ( https://wiki.php.net/rfc/enumerations ) about «enum sets». However, I do not quite understand why we can not now add a cast to scalars (string and int) and math expressions, which would solve this problem? This behavior has already been implemented for GMP objects. $mask = gmp_init(0b0001) | gmp_init(0b0010); // object(GMP) { num = 3; } echo $mask; // 3   $mask = $mask + 1; // object(GMP) { num = 4; } $mask instanceof \GMP; // true   I mean, for such cases, we can create a new "virtual enum case" containing a new value instead special «EnumSetCase».   enum Some: int {     case A = 0b0001;     case B = 0b0010; }   var_dump(Some::A | Some::B); // enum(Some::@anonymous) { value = 3; }   I don’t think that it is necessary to consider the «enum sets» as a separate case, cause addition is also a fairly popular case:   case LAST = self::B + 1;   Like any other mathematical operations.     ----------------------------------------------------------------------   -- Kirill Nesmeyanov  

« previous php.internals (#115609) next »