Booleans are the simplest type in the Swift language.
They’re simply true
or false
. The most basic language primitive you could imagine.
I was so naïve.
We only see the public interface of the Swift Bool
. Much like seeing a sausage made; vivisecting its innards in the source code might put you off forever.
A Frozen Struct
// Bool.swift
@frozen
public struct Bool: Sendable {
// ...
That’s right. Like all the basic Swift types you know and love, Bool
is a struct masquerading as a native language feature.
It’s marked @frozen
— so instance properties can’t be added or removed. This ensures the memory layout (i.e. number of bits) used is constant between Standard Library versions, which is critical for ABI stability.
Bool
is Sendable
, so the compiler doesn’t throw a fit when you to pass it between threads.
Let’s keep spelunking through the type.
Builtins.Int1
Four lines deep and we hit our second big WTF moment. Sit down and compose yourself.
public struct Bool: Sendable {
@usableFromInline
internal var _value: Builtin.Int1
// ...
The Swift Bool
lives a double-life. The duplicitous struct has just one instance property — a 1-bit integer.
Think that’s okay? Think again. It isn’t even a real Int
!
It’s a Builtin type, Int1
, which maps directly to an LLVM instruction deep in the guts of the Swift compiler. This stores a single bit instead of the hefty 64 bits that a regular Swift Int
requires on modern hardware. This is really as close to binary as it comes: a 1
or a 0
.
ExpressibleByBooleanLiteral
The Swift Standard Library conspires to pull wool over our eyes by conforming to the ExpressibleByBooleanLiteral
protocol — which allows us to instantiate a Boolean using true
or false
literals, instead of as a simple struct.
This defines an initialiser:
public protocol ExpressibleByBooleanLiteral {
init(booleanLiteral value: BooleanLiteralType)
}
This isn’t meant to be called directly. Assignment operations with literals such as let isActive = true
are chloroformed, stuffed in a van, and replaced with this initialiser during compilation.
This same process instantiates all the literals you thought you knew, such as ExpressibleByStringLiteral
, ExpressibleByIntegerLiteral
, and ExpressibleByDictionaryLiteral
.
Logical operations
Let’s end by checking how Boolean logic is implemented.
It ranges from quaint short-circuit evaluation:
// OR (||)
return lhs ? true : try rhs()
// AND (&&)
return lhs ? try rhs() : false
To truly deranged Builtin functions:
// ==
return Bool(Builtin.cmp_eq_Int1(lhs._value, rhs._value))
// NOT (!)
return Bool(Builtin.xor_Int1(a._value, true._value))
I hope you learned today to never trust a 1-bit integer. They make up everything.