I've found that when a static protocol method in turn calls a protocol instance method, the version of the instance method that gets called is less 'specialized' which is confusing me. Moreover, static protocol operator dispatch behaves differently than static protocol method dispatch, which is also confusing. Probably easier to explain with the following example:
infix operator •: MultiplicationPrecedence
protocol RectangularNumericArray {
associatedtype Element:Numeric
init()
static func •(lhs:Self, rhs:Self) -> Self
static func innerProduct(of lhs:Self, with rhs:Self) -> Self
func innerProduct(with rhs:Self, transposingRhs:Bool) -> Self
}
extension RectangularNumericArray {
static func •(lhs:Self, rhs:Self) -> Self {
print("slow default static (operator) method impl")
return lhs.innerProduct(with: rhs, transposingRhs: false)
}
static func innerProduct(of lhs:Self, with rhs:Self) -> Self {
print("slow default static method impl")
return lhs.innerProduct(with: rhs, transposingRhs: false)
}
func innerProduct(with rhs:Self, transposingRhs:Bool) -> Self{
print("slow default instance method impl")
return Self()
}
}
extension RectangularNumericArray where Element == Float32 {
static func •(_ lhs:Self, _ rhs:Self) -> Self {
print("fast specialized static (operator) method impl")
return lhs.innerProduct(with: rhs, transposingRhs:false)
}
static func innerProduct(of lhs:Self, with rhs:Self) -> Self {
print("fast specialized static method impl")
return lhs.innerProduct(with: rhs, transposingRhs: false)
}
func innerProduct(with rhs:Self, transposingRhs:Bool) -> Self {
print("fast specialized instance method impl")
return Self()
}
}
struct Matrix<T:Numeric> {
}
extension Matrix : RectangularNumericArray{
typealias Element = T
}
let M1 = Matrix<Float32>()
let M2 = Matrix<Float32>()
let _ = M1 • M2
print("-------------------------")
let _ = Matrix<Float32>.innerProduct(of: M1, with: M2)
print("-------------------------")
let _ = M1.innerProduct(with: M2, transposingRhs: false)
I would expect that the fast specialized implementation would get called in all cases, because I'm only ever using the appropriately specialized types. What I actually get is the following:
slow default static (operator) method impl
slow default instance method impl
-------------------------
fast specialized static method impl
slow default instance method impl
-------------------------
fast specialized instance method impl
Program ended with exit code: 0
This is with Xcode 13.3 beta 2.
Thanks to anyone who can help me understand,
Matt