swift

What's the difference between declaring a protocol with/without any word?


Consider these 2 declarations:

let a: any Protocol 

and

let a: Protocol

Is there any difference?


Solution

  • This is called the "existential any".

    When you use a protocol type as the type of a variable or function return type etc, that type is an existential type. Compared to concrete types (e.g. classes, structs), existential types have more limitations and also performance implications. Here is an example from the Swift Evolution proposal, illustrating the difference.

    protocol P {
      associatedtype A
      func test(a: A)
    }
    
    func generic<ConcreteP: P>(p: ConcreteP, value: ConcreteP.A) {
      p.test(a: value)
    }
    
    func useExistential(p: P) {
      generic(p: p, value: ???) // what type of value would P.A be??
    }
    

    Before any was introduced, you write existential types and concrete types the same way - by just writing their names. This makes it not very clear what is an existential type and what isn't. Since existential types behave very differently, it is useful to explicitly tell the reader that "this is an existential type". This is what any is for.

    See also the Motivation section.

    From Swift 6 and onwards, all existential types must be written with the any prefix.

    In Swift 5, you are still allowed to write protocol types that has no associated type/Self requirements, without the any. See also the Source Compatibility section.

    To minimize the amount of new code written that will become invalid in Swift 6, I propose requiring any immediately for protocols with Self and associated type requirements.

    This is why P and any P are both valid. They mean the same thing - the existential type any P. In Swift 6, though, writing P here would not be valid.