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

Matthew Johnson matthew at anandabits.com
Tue Jun 7 09:45:53 CDT 2016

> On Jun 6, 2016, at 12:22 AM, Dave Abrahams <dabrahams at apple.com> wrote:
> on Sun Jun 05 2016, Matthew Johnson <matthew-AT-anandabits.com <http://matthew-at-anandabits.com/>> wrote:
>> Sent from my iPhone
>>> On Jun 5, 2016, at 3:51 PM, Dave Abrahams via swift-evolution
>>> <swift-evolution at swift.org> wrote:
>>>> on Wed May 25 2016, Matthew Johnson <swift-evolution at swift.org> wrote:
>>>> Sent from my iPad
>>>>> On May 25, 2016, at 12:10 PM, Jordan Rose via swift-evolution
>>>>> <swift-evolution at swift.org> wrote:
>>>>>>> On May 25, 2016, at 05:27, Brent Royal-Gordon via swift-evolution
>>>>>>> <swift-evolution at swift.org> wrote:
>>>>>>> AFAIK an existential type is a type T with type parameters that
>>>>>>> are still abstract (see for example
>>>>>>> https://en.wikipedia.org/wiki/Type_system#Existential_types),
>>>>>>> i.e. have not been assigned concrete values.
>>>>>> My understanding is that, in Swift, the instance used to store
>>>>>> something whose concrete type is unknown (i.e. is still abstract),
>>>>>> but which is known to conform to some protocol, is called an
>>>>>> "existential". Protocols with associated values cannot be packed
>>>>>> into normal existentials because, even though we know that the
>>>>>> concrete type conforms to some protocol, the associated types
>>>>>> represent additional unknowns, and Swift cannot be sure how to
>>>>>> translate uses of those unknown types into callable members. Hence,
>>>>>> protocols with associated types are sometimes called
>>>>>> "non-existential".
>>>>>> If I am misusing the terminology in this area, please understand
>>>>>> that that's what I mean when I use that word.
>>>>> We’re not consistent about it, but an “existential value” is a value
>>>>> with protocol or protocol composition type. My mnemonic for this is
>>>>> that all we know is that certain operations exist (unlike a generic
>>>>> value, where we also have access to the type). John could explain it
>>>>> more formally. We sometimes use “existentials” as a (noun) shorthand
>>>>> for “existential value”.
>>>>> In the compiler source, all protocols and protocol compositions are
>>>>> referred to as “existential types”, whether they have associated
>>>>> types or not. Again, a protocol asserts the existence (and
>>>>> semantics) of various operations, but nothing else about the
>>>>> conforming type. (Except perhaps that it’s a class.) All protocols
>>>>> are thus “existential types” whether or not the language supports
>>>>> values having that type.
>>>>> It is incorrect to say that protocols with associated types (or
>>>>> requirements involving Self) are “non-existential”.
>>>> I haven't heard people using this term myself, but I imagine they
>>>> probably mean "can't form an existential value with the protocol".
>>>> There certainly appears to be a lot of confusion in the community with
>>>> many not realizing that this is a temporary limitation of the
>>>> implementation, not a necessary fact.
>>> As far as I know there is no known way to make protocols with Self
>>> requirements usefully “existentiable,” or whatever you want to call it.
>>> So unless I'm missing something, in this respect, the limitation is not
>>> temporary at all.
>> Take a look at the Equatable example in the opening existentials
>> section of Doug's manifesto:
>> https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011666.html
> Yes, note that I said *usefully* “existential.”

Fair enough.  But note that I was only talking about the inability to form and open such an existential which appears likely to be a temporary limitation given the generics manifesto (of course things could change).

>  While we can of
> course downcast in this way, you have to handle the failure case and
> it's not like you can use this to make a heterogeneous Set<Hashable>.
> AFAICT, this is not at all like what happens with associated types,
> where Collection<Element: Int> has obvious uses.

We can’t use this to form Set<Hashable> because existentials don’t conform to the protocol.  I know there is complexity in implementing this and it is not possible to synthesize conformance of the existential for all protocols, but AFAIK it isn’t a settled point that we won’t try to improve the situation in some way.  Maybe we can make progress here somehow.  

In the meantime, we can make a simple wrapper type to provide the required conformance and make a Set<HashableWrapper> that allows us to put Hashable into a Set.  This isn’t ideal but it is a lot less boilerplate than is involved in manual type erasure today where you need to define a struct, base class, and wrapper class.  I’d say that’s a win even if we’d like to do better in the future.

struct HashableWrapper: Hashable {
    var value: Hashable
    public var hashValue: Int { return base.hashValue }

public func ==(lhs: HashableWrapper, res: HashableWrapper) -> Bool {
    if let lhsValue = lhs.value openas T {     // T is a the type of lhsValue, a copy of the value stored in lhs
        if let rhsValue = rhs.value as? T {      // is res also a T?
            // okay: lhsValue and rhsValue are both of type T, which we know is Equatable
            if lhsValue == rhsValue { 
                return true
    return false

(We could also do this with a generic Wrapper<T> and conditional conformance in an `extension Wrapper: Hashable where T == Hashable` if we don’t want a bunch of wrapper types laying around)


> -- 
> -Dave

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160607/34800b5c/attachment.html>

More information about the swift-evolution mailing list