Try to run the attached code in Playground, and you'll notice two things:
1) The compiler will tell you the cast from Bar to IFooComparer will always succeed (line 23).
2) Yet you will get a runtime error of EXC_BAD_ACCESS when using the cast result (line 24).
The root problem seems to come from the "where Self: Foo" constraint on the IFooComparer protocol (line 9). Without that constraint, the code will run fine. Alternatively, if the code calls compareTo() on the Bar instance directly instead of the cast comparer instance, it will run fine as well.
This seems like an unexpected behavior of the runtime protocol constraint check. Can anyone shed some light on the issue? Thanks!
class Foo {
let val: Int
init(_ val: Int) {
self.val = val
}
}
protocol IFooComparer where Self: Foo {
func compareTo(other: Foo) -> Bool?
}
class Bar : Foo, IFooComparer {
func compareTo(other: Foo) -> Bool? {
guard let otherBar = other as? Bar else { return nil }
return self.val < otherBar.val
}
}
let bar1 = Bar(1)
let bar2 = Bar(2)
if let comparer = bar1 as? IFooComparer {
if let result = comparer.compareTo(other: bar2) {
print("\(bar1.val): \(result)")
} else {
print("\(bar1.val): Cannot compare")
}
}