>>
>> 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
 

Reply via email to