Behavior of existentials vs. concrete erased types

The use case around existentials in Swift and concrete type erasure proxies is very similar, both mechanisms allow us to abstract away the concrete implementation type of a value and expose the value only as its contextual base requirements.

There are a few different mechanisms for type erasure in play currently. We have types such as AnyView where a concrete subtype wraps and hides the actual view. We have supertypes such as AnyKeyPath where the supertype exposes only the base requirements, allowing us to erase the specifics of the subtype when we typecast the value.

We also have existentials such as any P, which allow us to type values purely by their protocol requirements.

We notice, however, that in Swift, existentials come with many down-sides. They cannot be assigned to generics parameters, their usage is incompatible with associated types, etc.

We also notice that if users find value in using type erasure to architect their applications, creating custom type erasure types is a huge hassle involving creating duplicating type definitions and concrete type wrappers. A hassle which might be avoided if we could simply adopt the any P mechanism consistently for the purposes of type erasure, foregoing the need for AnyP wrapper types.

Is there an analysis that I can find about why Swift has gone the route of encouraging type erasure through wrapper types rather than elevating the capabilities of its protocol existentials to first-class types? How come protocol existentials do not behave the same way as concrete type wrappers do? (eg. relating issues such as access to static members)

Naively, it seems like this area is ripe for rich improvements to the language's usability, in particular considering how many concrete type wrappers are duplicating definitions in Swift's standard library and Apple's API, never mind users' own desire to create and expose healthy library APIs and modular application code.

2 Likes

We don't intentionally encourage manual type erasure; it's been a matter of development priorities that we haven't had time to flesh out the implementation of built-in existential types, and so manual type erasure has been necessary to overcome those limitations. However, we are now actively working on breaking down some of these limitations:

You are right that in the fullness of time, built-in existential types ought to be sufficient and manual type erasure should become unnecessary.

14 Likes