Resolving the correct function by conditional conformance

Your analysis is correct, and I'm not sure there's a better answer. Swift generics are not like C++ templates—they have to use the same implementation every time, making the best possible choice given the information at the place where you wrote a call. The only way to get behavior based on a generic parameter's type at run time in Swift is to use:

  • protocols (by implementing requirements)
  • classes (by overriding)
  • closures (by passing around the actual implementation to use)
  • explicit checking (with as? or similar, which unfortunately doesn't work with protocols that have associated types)

Your solution instead just exposes two implementations of compute in the hopes that the caller will have more context than A does. That's also valid, but I agree that it's a little clunky because it leads to duplicated code. It also wouldn't help if the caller was itself using A in some generic way.