Easy TypeErasure

TypeErasure is certainly possible right now, but it is a pain in the butt, and difficult to implement correctly. Once you have the correct boilerplate written, it makes it difficult to change things because you have to change them in 3~4 different places. It seems to me that the compiler could write these thunks pretty easily... we just need some syntax to be able to think of the erased versions as a different type from the un-erased versions.

There are two kinds of type erasure to consider:

  1. Type Erasing generics from Structs/Types
  2. Type Erasing associatedtypes from Protocols

Let's start with types:

Let's say we have a struct:

struct Foo<T,U> {
    let t:T
    let u:U

The syntax I would like to see is allowing _ to erase any particular generic. So Foo<_,U> would generate a thunk with the following:

struct Foo<_,U> {
    let t:Any //This would still have any restrictions that T had on it (e.g. hashable)
    let u:U

To get the original struct back you would use as? or as!:

let erasedFoo:Foo<_,_> = myFoo 
let foo:Foo<T,U>? = erasedFoo as? Foo<T,U>

Next, let's look at protocols. There are a couple of ways we could go here.

I really like the idea of having an Any<Protocol> syntax which would allow you to refer to and store protocols with self and associatedtype requirements.

The other option would be to allow a where clause in the definition to either define or erase the problematic requirements. For example, if we have a protocol Bar:

protocol Bar {
    associatedtype Element
    var element:Element {get} 

If we want to use this as a variable we can't:

var bar:Bar //Error: Can only be used as a constraint because of associated type

We could allow a where clause to define away the ambiguity:

var bar:Bar where Bar.Element == Int

Or if we want to type erase Element, we could use _ again:

var bar:Bar where Bar.Element == _

You could also type alias it to avoid writing everything over and over:

typealias AnyBar = Bar where Bar.Element = _
var bar:AnyBar

Again, we would want to be able to recover the true type with as? and as!

Anyway, I am sure I have forgotten something (feel free to correct me), but I wanted to get a discussion started since I run into this all the time. Seriously. It is my #1 frustration with Swift...


You might want to check out Swift Generics Manifesto and in particular the existentials in there.

I think we all want this, but it's gonna take a while more before all of it is implemented.