You can use any ExpressibleByIntegerLiteral (or StringLiteral) as an enum’s raw type, or you can implement RawRepresentable yourself. But for non-@objc enums, having the constants inline is only shorthand for the two switch statements that appear in RawRepresentable’s requirements, it has no other effect. I’m not saying it’s not nice shorthand, but there’s nothing special going on here.
EDIT: so if you could have your cake and eat it too, what would the rule actually be? What code turns 0xC2_000000 into an Int32?
the issue with that is that you need to keep the rawValue and the init(rawValue:) sides in sync with one another.
the rule would be the extension TagBits:RawRepresentable block in my original post. the justification is that RawRepresentable and its requirements are meant to work with generics (especially other protocols), but the literal constants are just there to provide a consistent mapping. so the mapping logic should go through init(literalValue:) and literalValue instead of piggybacking on RawRepresentable.
Where are the Cx constants coming from? Can't this work for you instead?
enum TagBits: Int32, Sendable {
case polygon = -0x40_000000 // for 0xC0_000000
case square = -0x3E_000000 // for 0xC2_000000
case triangle = -0x3D_000000 // for 0xC3_000000
}
Might be a bit inconvenient to go downwards (0, f, e, ...) rather than upwards (0, 1, 2), but this seems to be quite rare/niche use case.