Method Dispatch for Methods in Protocol Extensions in Separate Modules

Hello,

Project Layout

Let there be a Swift executable project with the following layout (https://gitlab.com/Frizlab/swift-test-modules-and-protocol-extensions):

  • The Protocol target which defines an empty protocol named Protocol;
  • The Extension target which depends on Protocol and defines an extension to Protocol with a function hello() and a default implementation for the function (we have to define an implementation because we’re in a protocol extension);
  • The main target which depends on both previous targets and creates a concrete implementation (named Implementation) of Protocol which implements the method defined in the extension.

My problem

When is the default implementation of the protocol called vs. the concrete implementation? Also, is the current behaviour the expected behaviour?

Tests

In the main module, let there be a variable implem which is an instance of Implementation.

The concrete non-default implementation of the hello() method is only called in two cases:

  • Calling the hello() method directly on the object;
  • Calling the hello() method in a function that takes an Implementation argument.

These are the other tests I did that call the default implementation of the method:

  • Calling the hello() method in the main module in a function that takes a Protocol argument;
  • Calling the hello() method in the main module in a generic function that takes a P argument where P: Protocol;
  • Same cases with the methods in the Extension module.

My Thoughts

I understand the method dispatch in Swift is not as dynamic as Objective-C. However, for the generic case at least, I’d have expected it to be smart enough to dispatch the hello() call to the concrete implementation instead of the default one.

I think in their current form, protocol extensions are pretty much useless when defined in an external module. Whenever a method from the extension is called in said module, there is no way the actual concrete implementation of a method defined in the extension is called. Does anybody has any insights on this?

Thank you very much.

Modules have nothing to do with this.

Protocol requirements are customization points, and they are dynamically dispatched.

Extension methods which are *not* protocol requirements, are not customization points.

2 Likes

Oh. It appears you’re right :frowning:

I tested with a protocol and extensions in the same module and when calling from a method which takes the protocol as parameter, the default implementation is called.

Which begs the question: is it possible to extend protocols with a dynamic dispatch? Otherwise protocol extensions would not be very useful, would they?

If the extension is visible from the place you declare conformance to a protocol, then its methods are available as candidates to be chosen to satisfy a protocol requirement. The mapping of protocol requirements to implementations is fixed from the context the protocol conformance is declared, though, and can't be dynamically modified once established. This is to prevent the problems with ObjC categories clashing and unexpectedly changing the behavior of other unrelated code at runtime.

It would be a useful future extension for extensions to be able to add new dynamically-dispatched requirements to protocols, but currently extensions only add methods to types that conform to the protocol, not to the protocol itself.

1 Like

Alright, thank you very much for your explanations. I hope we’ll see dynamically-dispatched requirements in protocol extensions soon! In the mean time I’ll work around it.