SE-0309: Unlock existential types for all protocols

@Joe_Groff and I discussed off-forum briefly. My team has a use case in favour of this proposal.

We've got a protocol for a type whose instances may cross process boundaries as XPC messages; for the sake of this discussion, let's call it Action. Action has two associated types, Input: Codable and Output: Codable, and an instance member, func invoke(passing input: Input) throws -> Output. Conforming types implement invoke(passing:) in order to transform an Input into an Output. Nothing too Earth-shattering there. :slight_smile:

Now, we want to refer to individual instances of Action in a generic context because:

  • we need to enforce type safety and security across the process boundary by defining an array of Action.Types that can be safely decoded after transmission; and
  • we want to be able to look up which Action.Type needs to be instantiated and invoked in said array.

But because of Action's associated type requirements, we can't create an Array<Action.Type> directly. We instead need to create a type-erased AnyAction protocol with no associated type requirements. In our case, we imbue this protocol with a single member function static func invoke(usingContentsOf xpcDictionary: xpc_object_t) -> Void, and we make Action conform to it. Action provides a default implementation that does very little: it decodes an instance of Self, decodes an instance of Input, invokes invoke(passing:), and yields either an Output or an Error as an XPC reply. This function has no associated type or Self requirements in its interface—they're all part of its implementation. If we could refer to Action as an existential type, then AnyAction would be unnecessary. We could make invoke(usingContentsOf:) a member of Action and could remove AnyAction from our project.

tl;dr: We have a real-world use case for referring to a protocol with associated types as an existential type. If this proposal is accepted, we'd be able to drop AnyAction and use Action directly in its place, which would mean the elimination of a fair bit of boilerplate and glue.

22 Likes