i was rather surprised that this does not work:
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 of Bool? and the answer is database schema, because i want to encode this to BSON using RawRepresentable.
jrose
(Jordan Rose)
2
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.
Pippin
(Ethan Pippin)
3
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...
4 Likes
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 ==(_:_:)…
2 Likes
jrose
(Jordan Rose)
5
Yeah, you hit the not-quite-bug of the RawRepresentable ==…
tera
6
Same bug as this?
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
}
}
2 Likes
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.
1 Like
tera
8
Interestingly, this compiles and works fine (but obviously bad):
extension Bool: ExpressibleByIntegerLiteral {
public init(integerLiteral value: Int) { fatalError("don't call") }
}
enum Verification: Bool {
case again = false
case debut = true
}
Well spotted. I wonder what is the intended use-case here.
2 Likes
Nobody1707
(Nobody1707)
9
Does it still call the RawRepresentable version of == if you move the RawRepresentable conformance to a separate file from the enum?