Engineering Blog

Swift Protocol Static Function Selection Quirk

I've been writing a lot of heavily generic Swift code lately, and figured out what seems (to me at least) to be a really useful quirk/edge-case having to do with how Swift selects between a protocol extension static method, and a static method implemented on a conforming type.

Consider this Swift code:

protocol Animal {
  static var type: String { get }
}

extension Animal {
  static func greeting() -> String {
    return "I am an animal of type: \(type)"
  }
}

struct Cat: Animal {
 static var type = "Cat"

 static func greeting() -> String {
    return "Meow, I'm a cute Cat"
  }
}

func greet<A: Animal>(_ AnimalType: A.Type) {
  print(AnimalType.greeting())
}

greet(Cat.self) // 🧐 what will this line print ???

My intuition was that the line marked would print "Meow, I'm a cute Cat", but in fact it prints "I am an animal of type: Cat", with Swift for some reason choosing the generic, fallback method supplied as a protocol extension instead of the specific implementation provided by the conforming type.

I've run into this seemingly wrong function selection in a way that was pretty frustrating for a ORM-type Swift library I've been working on. However, I just figured out that I can get Swift to use the correct method by also declaring the function as protocol requirement, that is, by adding the line marked below:

protocol Animal {
  static var type: String { get }
  static func greeting() -> String // 👋 🎉 this fixes the issue
}
Gertrude

The Gertrude mac app helps you protect your kids online with strict internet filtering that you can manage from your own computer or phone, plus remote monitoring of screenshots and keylogging. $5/mo, with a 60 day free trial.

Start free trial →