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