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