In fact, it does not know that both sides are of type Bool
, because ==
can be implemented to compare heterogeneous types and false
can be any type that's expressible by a Boolean literal. Therefore, it has to figure out every possible combination of implementations of ==
and types conforming to ExpressibleByBooleanLiteral
that is available for use here to see if it's a better match.
struct S: ExpressibleByBooleanLiteral {
init(booleanLiteral value: Bool) { }
// Note that this type has no storage.
// It throws away the literal value.
}
func == (lhs: Bool, rhs: S) { print("Hello") }
// Note that this `==` doesn't even return any value.
typealias BooleanLiteralType = S
false == true
// Prints "Hello".
// Note that no actual comparison is being done here.
// `==` is literally just a function that prints "Hello".
For numeric types specifically, there is a hardcoded compiler shortcut to make compile times tolerable until a general solution is discovered. No such optimization is hardcoded for Boolean values because it's not idiomatic to write == true
and == false
. If you do, it'll still work, but the compiler will look through every possible implementation for the best match. As @jonprescott as said, you've discovered the solution: don't write this.