Introduction of new keyword 'any' for protocol conforming arguments

This diagnostic has been rewritten a few times, so you may have previously seen alternate forms:

  • Swift 5.2: error: value of protocol type 'Drivable' cannot conform to 'Drivable'; only struct/enum/class types can conform to protocols
  • Swift 5.1: error: protocol type 'Drivable' cannot conform to 'Drivable' because only concrete types can conform to protocols
  • Swift 4.2.4: error: cannot invoke 'startTravelingG' with an argument list of type '(with: Drivable)'

In any case, this method call has never been possible.

Perhaps! As @gwendal.roue points out above, there is some exploration in [Pitch] Implicitly opening existentials for formalizing the existential → generic conversion, but I think it's something that requires a lot of thought in terms of the language design, from the top down. (e.g., if it's possible to open an existential, should generic methods be implicitly callable with existential parameters, assuming valid constraints? And if so, what becomes the effective difference between existential types and concrete types, if any at all? Maybe nothing!)

My post above had more in mind the state of things today, though things could definitely change in the future. It's a question worth asking.


One thing I wanted to point out about generic methods regarding their capture of the static, compile-time type to be exposed at runtime:

class A {}
class B: A {}

func f<T>(_ t: T) {
  print(T.self, "<=>", type(of: t))
}

f(A()) // A <=> A
f(B()) // B <=> B
f(B() as A) // A <=> B     <<---------

Part of the reason that you can't call a generic method with an existential is that the static type isn't known, but if the waters between existential and concrete types above do get muddied a bit, and you could call a generic method with an existential parameter, you can imagine the generic being instantiated with the runtime type inside of the existential container.

If that does become possible, API consumers may need to be a lot more careful and aware of the types they're passing around: if a method goes from returning some P to any P and the result is passed to another generic method, the results may change considerably!

4 Likes