Note that you can use constrained existentials in limited ways on older deployment targets, and those ways are powerful enough that you can almost get to feature parity, just in a less convenient way than you can on newer deployment targets. In particular, you can declare parameters, variables, properties, and return values as having a constrained protocol type. So while the restrictions mean you can't have a generic type argument that's a constrained existential type (and therefore you can't write e.g. [Collection<Int>]
), you can make a struct
which wraps a constrained existential type and then use that struct as a generic type argument (e.g. [MyCollection<Int>]
).
The only hard restriction is that you can't cast to these types until you bump your deployment target to iOS 16.