[swift-evolution-announce] [Review] SE-0089: Replace protocol<P1, P2> syntax with Any<P1, P2>

(Thorsten Seitz) #1

I'd like to reiterate that an existential is a protocol with self type requirements and/or associated types that have not been assigned. Protocols without self type requirements or associated types are *not* existentials!

(Neither would be protocols where all associated types have been assigned (this makes only sense for associated types inherited from another protocol and is currently not possibly in Swift if I am not mistaken)).

We should not confuse this.



Am 25. Mai 2016 um 12:23 schrieb Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org>:

However, I believe this would have a significant advantage: it would clarify the distinction between an existential and a constraint. It would more clearly mark where you are taking on the abstraction overhead of an existential. It would also improve the non-existential type situation: in the short term, it would make it clearer where uses of associated type protocols like `Comparable` would not be permitted; in the long term, once we have type-erased existentials for those protocols, it would make it clearer when type erasure was in effect.

Sorry to self-reply, but I had some additional thoughts on this.

Swift's type system has a logical hierarchy of types. A type's supertypes include any protocols it conforms to, and then the protocols they conform to, ultimately rooted at Any. Additionally, a class's supertypes include its superclass, and then its superclass, and so on up to a root class, and then AnyObject, and finally Any once more. And of course, Any<…> lets you build composite types out of several protocols which fit into this framework: Any<Foo, Bar> is a subtype of both Foo and Bar and a supertype of any type which conforms to both Foo and Bar.

At an implementation level, however, this is only partially true. A class can be transformed into its superclass, all the way up to AnyObject, without any change in memory representation. But once you enter the world of protocols, everything changes. To cast to a protocol, you must place the instance in an existential, a different instance with a different memory layout. This can have significant performance consequences; for example, it's the reason you can't use `as` to convert an array of instances to an array of some protocol they all belong to.

Requiring the use of `Any<…>` to mark any existential would help reinforce this distinction. It would give users a better understanding of what their code was actually doing and why they might not be able to do things like make certain seemingly sensible casts.

(Although technically, this would seem to imply that AnyObject's future equivalent should *not* require an Any<>. Hmm.)

Brent Royal-Gordon

swift-evolution mailing list