extension KYC
{
@frozen public
enum Verification:Bool, Equatable, Sendable
{
case again = false
case debut = true
}
}
error: raw type 'Bool' is not expressible by a string, integer,
or floating-point literal
you may ask, why do you even need an enum with a raw type ofBool? and the answer is database schema, because i want to encode this to BSON using RawRepresentable.
Certainly seems reasonable to me. It’s nothing you can’t write yourself, but while argument labels make it less common to use an enum instead of a boolean they don’t cover all the circumstances where you’d want to do that.
Interesting to see that Bool cannot be conformed and have an automatic synthesis but the lexical structure says: raw-value-literal → numeric-literal | static-string-literal | boolean-literal...
i ended up shooting myself in the foot writing this, as this relatively simple sketch segfaults for some reason:
@frozen public
enum BooleanEnum:Equatable, Sendable
{
case a
case b
}
extension BooleanEnum:RawRepresentable
{
@inlinable public
init?(rawValue:Bool) { self = rawValue ? .a : .b }
@inlinable public
var rawValue:Bool { self == .a }
}
@main
enum Main
{
@inline(never) static
func getBooleanCase() -> BooleanEnum
{
return .a
}
static
func main() async throws
{
let _state:BooleanEnum = Self.getBooleanCase()
let hidden:Bool = _state != .a
print(hidden)
}
}
$ swiftc crash4.swift -parse-as-library
$ ./crash4
💣 Program crashed: Bad pointer dereference at 0x00007ffd9c0beff8
Thread 0 "crash4" crashed:
0 0x0000557fe2b3db1b BooleanEnum.rawValue.getter + 27 in crash4
1 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
2 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
3 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
4 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
5 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
6 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
7 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
8 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
9 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
10 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
11 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
12 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
13 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
14 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
15 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
16 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
17 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
18 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
19 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
20 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
21 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
22 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
23 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
24 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
25 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
26 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
27 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
28 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
29 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
30 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
...
112230 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
112231 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
112232 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
112233 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
112234 0x0000557fe2b3db3e BooleanEnum.rawValue.getter + 61 in crash4
112235 0x00007f050bf5986d == infix<A>(_:_:) + 124 in libswiftCore.so
112236 0x0000557fe2b3dd50 static Main.main() + 207 in crash4
112237 0x0000557fe2b3dfe0 static Main.$main() in crash4
i haven’t had time to investigate exactly what is going on (i literally just isolated this), but from the stack trace i’m guessing that me calling !=(_:_:) fell into some kind of infinite recursion.
EDIT: facepalm the default implementation of ==(_:_:), which the Equatable.!=(_:_:) operator calls, is accessing rawValue, which is calling itself with ==(_:_:)…
I don't think it's right for EQ to compare rawValues instead of enumeration tags, we had a thread on this recently. As a workaround I'd suggest to always override "==" when you adding RawRepresentable conformance, in this case:
public static func == (lhs: Self, rhs: Self) -> Bool {
switch (lhs, rhs) {
case (.a, .a), (.b, .b): true
case (.a, .b), (.b, .a): false
}
}
except i’m naturally not thrilled to have to write this every time (and i, or the AI code generator, might make a typo), it really ought to be something the compiler can generate automatically. it’s regrettable that the synthesized Equatable conformance gets disabled when enums have raw types.