I created two bug requests for Recursive protocol constraints and Nested 
generics and will write a proposal for Concrete same-type requirements.

[SR-1445] Recursive protocol constraints <https://bugs.swift.org/browse/SR-1445>

[SR-1446] Nested generics <https://bugs.swift.org/browse/SR-1446>
> On 03 May 2016, at 09:58, Douglas Gregor <dgre...@apple.com> wrote:
> 
> 
> 
> Sent from my iPhone
> 
> On May 2, 2016, at 3:58 PM, David Hart <da...@hartbit.com 
> <mailto:da...@hartbit.com>> wrote:
> 
>> I’d like to continue moving Completing Generics forward for Swift 3 with 
>> proposals. Can Douglas, or someone from the core team, tell me if the topics 
>> mentioned in Removing unnecessary restrictions require proposals or if bug 
>> reports should be opened for them instead?
> 
> I'd classify everything in that section as a bug, so long as we're 
> restricting ourselves to the syntax already present in the language. 
> Syntactic improvements (e.g., for same-type-to-concrete constraints) would 
> require a proposal. 
> 
>   - Doug
> 
> 
>> 
>>> On 03 Mar 2016, at 02:22, Douglas Gregor via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> Hi all,
>>> 
>>> Introduction
>>> 
>>> The “Complete Generics” goal for Swift 3 has been fairly ill-defined thus 
>>> fair, with just this short blurb in the list of goals:
>>> 
>>> Complete generics: Generics are used pervasively in a number of Swift 
>>> libraries, especially the standard library. However, there are a number of 
>>> generics features the standard library requires to fully realize its 
>>> vision, including recursive protocol constraints, the ability to make a 
>>> constrained extension conform to a new protocol (i.e., an array of 
>>> Equatable elements is Equatable), and so on. Swift 3.0 should provide those 
>>> generics features needed by the standard library, because they affect the 
>>> standard library's ABI.
>>> This message expands upon the notion of “completing generics”. It is not a 
>>> plan for Swift 3, nor an official core team communication, but it collects 
>>> the results of numerous discussions among the core team and Swift 
>>> developers, both of the compiler and the standard library. I hope to 
>>> achieve several things:
>>> 
>>> Communicate a vision for Swift generics, building on the original generics 
>>> design document 
>>> <https://github.com/apple/swift/blob/master/docs/Generics.rst>, so we have 
>>> something concrete and comprehensive to discuss.
>>> Establish some terminology that the Swift developers have been using for 
>>> these features, so our discussions can be more productive (“oh, you’re 
>>> proposing what we refer to as ‘conditional conformances’; go look over at 
>>> this thread”).
>>> Engage more of the community in discussions of specific generics features, 
>>> so we can coalesce around designs for public review. And maybe even get 
>>> some of them implemented.
>>> 
>>> A message like this can easily turn into a centithread 
>>> <http://www.urbandictionary.com/define.php?term=centithread>. To separate 
>>> concerns in our discussion, I ask that replies to this specific thread be 
>>> limited to discussions of the vision as a whole: how the pieces fit 
>>> together, what pieces are missing, whether this is the right long-term 
>>> vision for Swift, and so on. For discussions of specific language features, 
>>> e.g., to work out the syntax and semantics of conditional conformances or 
>>> discuss the implementation in compiler or use in the standard library, 
>>> please start a new thread based on the feature names I’m using.
>>> 
>>> This message covers a lot of ground; I’ve attempted a rough categorization 
>>> of the various features, and kept the descriptions brief to limit the 
>>> overall length. Most of these aren’t my ideas, and any syntax I’m providing 
>>> is simply a way to express these ideas in code and is subject to change. 
>>> Not all of these features will happen, either soon or ever, but they are 
>>> intended to be a fairly complete whole that should mesh together. I’ve put 
>>> a * next to features that I think are important in the nearer term vs. 
>>> being interesting “some day”. Mostly, the *’s reflect features that will 
>>> have a significant impact on the Swift standard library’s design and 
>>> implementation.
>>> 
>>> Enough with the disclaimers; it’s time to talk features.
>>> 
>>> Removing unnecessary restrictions
>>> 
>>> There are a number of restrictions to the use of generics that fall out of 
>>> the implementation in the Swift compiler. Removal of these restrictions is 
>>> a matter of implementation only; one need not introduce new syntax or 
>>> semantics to realize them. I’m listing them for two reasons: first, it’s an 
>>> acknowledgment that these features are intended to exist in the model we 
>>> have today, and, second, we’d love help with the implementation of these 
>>> features.
>>> 
>>> 
>>> *Recursive protocol constraints
>>> 
>>> Currently, an associated type cannot be required to conform to its 
>>> enclosing protocol (or any protocol that inherits that protocol). For 
>>> example, in the standard library SubSequence type of a Sequence should 
>>> itself be a Sequence:
>>> 
>>> protocol Sequence {
>>>   associatedtype Iterator : IteratorProtocol
>>>   …
>>>   associatedtype SubSequence : Sequence   // currently ill-formed, but 
>>> should be possible
>>> }
>>> 
>>> The compiler currently rejects this protocol, which is unfortunate: it 
>>> effectively pushes the SubSequence-must-be-a-Sequence requirement into 
>>> every consumer of SubSequence, and does not communicate the intent of this 
>>> abstraction well.
>>> 
>>> Nested generics
>>> 
>>> Currently, a generic type cannot be nested within another generic type, e.g.
>>> 
>>> struct X<T> {
>>>   struct Y<U> { }  // currently ill-formed, but should be possible
>>> }
>>> 
>>> There isn’t much to say about this: the compiler simply needs to be 
>>> improved to handle nested generics throughout.
>>> 
>>> 
>>> Concrete same-type requirements
>>> 
>>> Currently, a constrained extension cannot use a same-type constraint to 
>>> make a type parameter equivalent to a concrete type. For example:
>>> 
>>> extension Array where Element == String {
>>>   func makeSentence() -> String {
>>>     // uppercase first string, concatenate with spaces, add a period, 
>>> whatever
>>>   }
>>> }
>>> 
>>> This is a highly-requested feature that fits into the existing syntax and 
>>> semantics. Note that one could imagine introducing new syntax, e.g., 
>>> extending “Array<String>”, which gets into new-feature territory: see the 
>>> section on “Parameterized extensions”.
>>> 
>>> Parameterizing other declarations
>>> 
>>> There are a number of Swift declarations that currently cannot have generic 
>>> parameters; some of those have fairly natural extensions to generic forms 
>>> that maintain their current syntax and semantics, but become more powerful 
>>> when made generic.
>>> 
>>> Generic typealiases
>>> 
>>> Typealiases could be allowed to carry generic parameters. They would still 
>>> be aliases (i.e., they would not introduce new types). For example:
>>> 
>>> typealias StringDictionary<Value> = Dictionary<String, Value>
>>> 
>>> var d1 = StringDictionary<Int>()
>>> var d2: Dictionary<String, Int> = d1 // okay: d1 and d2 have the same type, 
>>> Dictionary<String, Int>
>>> 
>>> 
>>> Generic subscripts
>>> 
>>> Subscripts could be allowed to have generic parameters. For example, we 
>>> could introduce a generic subscript on a Collection that allows us to pull 
>>> out the values at an arbitrary set of indices:
>>> 
>>> extension Collection {
>>>   subscript<Indices: Sequence where Indices.Iterator.Element == 
>>> Index>(indices: Indices) -> [Iterator.Element] {
>>>     get {
>>>       var result = [Iterator.Element]()
>>>       for index in indices {
>>>         result.append(self[index])
>>>       }
>>> 
>>>       return result
>>>     }
>>> 
>>>     set {
>>>       for (index, value) in zip(indices, newValue) {
>>>         self[index] = value
>>>       }
>>>     }
>>>   }
>>> }
>>> 
>>> 
>>> Generic constants
>>> 
>>> let constants could be allowed to have generic parameters, such that they 
>>> produce differently-typed values depending on how they are used. For 
>>> example, this is particularly useful for named literal values, e.g.,
>>> 
>>> let π<T : FloatLiteralConvertible>: T = 
>>> 3.141592653589793238462643383279502884197169399
>>> 
>>> The Clang importer could make particularly good use of this when importing 
>>> macros.
>>> 
>>> 
>>> Parameterized extensions
>>> 
>>> Extensions themselves could be parameterized, which would allow some 
>>> structural pattern matching on types. For example, this would permit one to 
>>> extend an array of optional values, e.g.,
>>> 
>>> extension<T> Array where Element == T? {
>>>   var someValues: [T] {
>>>     var result = [T]()
>>>     for opt in self {
>>>       if let value = opt { result.append(value) }
>>>     }
>>>    return result
>>>   }
>>> }
>>> 
>>> We can generalize this to a protocol extensions:
>>> 
>>> extension<T> Sequence where Element == T? {
>>>   var someValues: [T] {
>>>     var result = [T]()
>>>     for opt in self {
>>>       if let value = opt { result.append(value) }
>>>     }
>>>    return result
>>>   }
>>> }
>>> 
>>> Note that when one is extending nominal types, we could simplify the syntax 
>>> somewhat to make the same-type constraint implicit in the syntax:
>>> 
>>> extension<T> Array<T?> {
>>>   var someValues: [T] {
>>>     var result = [T]()
>>>     for opt in self {
>>>       if let value = opt { result.append(value) }
>>>     }
>>>    return result
>>>   }
>>> }
>>> 
>>> When we’re working with concrete types, we can use that syntax to improve 
>>> the extension of concrete versions of generic types (per “Concrete 
>>> same-type requirements”, above), e.g.,
>>> 
>>> extension Array<String> {
>>>   func makeSentence() -> String {
>>>     // uppercase first string, concatenate with spaces, add a period, 
>>> whatever
>>>   }
>>> }
>>> 
>>> 
>>> Minor extensions
>>> 
>>> There are a number of minor extensions we can make to the generics system 
>>> that don’t fundamentally change what one can express in Swift, but which 
>>> can improve its expressivity.
>>> 
>>> *Arbitrary requirements in protocols
>>> 
>>> Currently, a new protocol can inherit from other protocols, introduce new 
>>> associated types, and add new conformance constraints to associated types 
>>> (by redeclaring an associated type from an inherited protocol). However, 
>>> one cannot express more general constraints. Building on the example from 
>>> “Recursive protocol constraints”, we really want the element type of a 
>>> Sequence’s SubSequence to be the same as the element type of the Sequence, 
>>> e.g.,
>>> 
>>> protocol Sequence {
>>>   associatedtype Iterator : IteratorProtocol
>>>   …
>>>   associatedtype SubSequence : Sequence where SubSequence.Iterator.Element 
>>> == Iterator.Element
>>> }
>>> 
>>> Hanging the where clause off the associated type is protocol not ideal, but 
>>> that’s a discussion for another thread.
>>> 
>>> 
>>> *Typealiases in protocols and protocol extensions
>>> 
>>> Now that associated types have their own keyword (thanks!), it’s reasonable 
>>> to bring back “typealias”. Again with the Sequence protocol:
>>> 
>>> protocol Sequence {
>>>   associatedtype Iterator : IteratorProtocol
>>>   typealias Element = Iterator.Element   // rejoice! now we can refer to 
>>> SomeSequence.Element rather than SomeSequence.Iterator.Element
>>> }
>>> 
>>> 
>>> Default generic arguments 
>>> 
>>> Generic parameters could be given the ability to provide default arguments, 
>>> which would be used in cases where the type argument is not specified and 
>>> type inference could not determine the type argument. For example:
>>> 
>>> public final class Promise<Value, Reason=Error> { … }
>>> 
>>> func getRandomPromise() -> Promise<Int, ErrorProtocol> { … }
>>> 
>>> var p1: Promise<Int> = …
>>> var p2: Promise<Int, Error> = p1     // okay: p1 and p2 have the same type 
>>> Promise<Int, Error>
>>> var p3: Promise = getRandomPromise() // p3 has type Promise<Int, 
>>> ErrorProtocol> due to type inference
>>> 
>>> 
>>> Generalized “class” constraints
>>> 
>>> The “class” constraint can currently only be used for defining protocols. 
>>> We could generalize it to associated type and type parameter declarations, 
>>> e.g.,
>>> 
>>> protocol P {
>>>   associatedtype A : class
>>> }
>>> 
>>> func foo<T : class>(t: T) { }
>>> 
>>> As part of this, the magical AnyObject protocol could be replaced with an 
>>> existential with a class bound, so that it becomes a typealias:
>>> 
>>> typealias AnyObject = protocol<class>
>>> 
>>> See the “Existentials” section, particularly “Generalized existentials”, 
>>> for more information.
>>> 
>>> 
>>> *Allowing subclasses to override requirements satisfied by defaults
>>> 
>>> When a superclass conforms to a protocol and has one of the protocol’s 
>>> requirements satisfied by a member of a protocol extension, that member 
>>> currently cannot be overridden by a subclass. For example:
>>> 
>>> protocol P {
>>>   func foo()
>>> }
>>> 
>>> extension P {
>>>   func foo() { print(“P”) }
>>> }
>>> 
>>> class C : P {
>>>   // gets the protocol extension’s 
>>> }
>>> 
>>> class D : C {
>>>   /*override not allowed!*/ func foo() { print(“D”) }
>>> }
>>> 
>>> let p: P = D()
>>> p.foo() // gotcha: prints “P” rather than “D”!
>>> 
>>> D.foo should be required to specify “override” and should be called 
>>> dynamically.
>>> 
>>> 
>>> Major extensions to the generics model
>>> 
>>> Unlike the minor extensions, major extensions to the generics model provide 
>>> more expressivity in the Swift generics system and, generally, have a much 
>>> more significant design and implementation cost.
>>> 
>>> 
>>> *Conditional conformances
>>> 
>>> Conditional conformances express the notion that a generic type will 
>>> conform to a particular protocol only under certain circumstances. For 
>>> example, Array is Equatable only when its elements are Equatable:
>>> 
>>> extension Array : Equatable where Element : Equatable { }
>>> 
>>> func ==<T : Equatable>(lhs: Array<T>, rhs: Array<T>) -> Bool { … }
>>> 
>>> Conditional conformances are a potentially very powerful feature. One 
>>> important aspect of this feature is how deal with or avoid overlapping 
>>> conformances. For example, imagine an adaptor over a Sequence that has 
>>> conditional conformances to Collection and MutableCollection:
>>> 
>>> struct SequenceAdaptor<S: Sequence> : Sequence { }
>>> extension SequenceAdaptor : Collection where S: Collection { … }
>>> extension SequenceAdaptor : MutableCollection where S: MutableCollection { }
>>> 
>>> This should almost certainly be permitted, but we need to cope with or 
>>> reject “overlapping” conformances:
>>> 
>>> extension SequenceAdaptor : Collection where S: 
>>> SomeOtherProtocolSimilarToCollection { } // trouble: two ways for 
>>> SequenceAdaptor to conform to Collection
>>> 
>>> See the section on “Private conformances” for more about the issues with 
>>> having the same type conform to the same protocol multiple times.
>>> 
>>> 
>>> Variadic generics
>>> 
>>> Currently, a generic parameter list contains a fixed number of generic 
>>> parameters. If one has a type that could generalize to any number of 
>>> generic parameters, the only real way to deal with it today involves 
>>> creating a set of types. For example, consider the standard library’s “zip” 
>>> function. It returns one of these when provided with two arguments to zip 
>>> together:
>>> 
>>> public struct Zip2Sequence<Sequence1 : Sequence,
>>>                            Sequence2 : Sequence> : Sequence { … }
>>> 
>>> public func zip<Sequence1 : Sequence, Sequence2 : Sequence>(
>>>               sequence1: Sequence1, _ sequence2: Sequence2)
>>>             -> Zip2Sequence<Sequence1, Sequence2> { … }
>>> 
>>> Supporting three arguments would require copy-paste of those of those:
>>> 
>>> public struct Zip3Sequence<Sequence1 : Sequence,
>>>                            Sequence2 : Sequence,
>>>                            Sequence3 : Sequence> : Sequence { … }
>>> 
>>> public func zip<Sequence1 : Sequence, Sequence2 : Sequence, Sequence3 : 
>>> Sequence>(
>>>               sequence1: Sequence1, _ sequence2: Sequence2, _ sequence3: 
>>> sequence3)
>>>             -> Zip3Sequence<Sequence1, Sequence2, Sequence3> { … }
>>> 
>>> Variadic generics would allow us to abstract over a set of generic 
>>> parameters. The syntax below is hopelessly influenced by C++11 variadic 
>>> templates <http://www.jot.fm/issues/issue_2008_02/article2/> (sorry), where 
>>> putting an ellipsis (“…”) to the left of a declaration makes it a 
>>> “parameter pack” containing zero or more parameters and putting an ellipsis 
>>> to the right of a type/expression/etc. expands the parameter packs within 
>>> that type/expression into separate arguments. The important part is that we 
>>> be able to meaningfully abstract over zero or more generic parameters, e.g.:
>>> 
>>> public struct ZipIterator<... Iterators : IteratorProtocol> : Iterator {  
>>> // zero or more type parameters, each of which conforms to IteratorProtocol
>>>   public typealias Element = (Iterators.Element...)                       
>>> // a tuple containing the element types of each iterator in Iterators
>>> 
>>>   var (...iterators): (Iterators...)    // zero or more stored properties, 
>>> one for each type in Iterators 
>>>   var reachedEnd: Bool = false
>>> 
>>>   public mutating func next() -> Element? {
>>>     if reachedEnd { return nil }
>>> 
>>>     guard let values = (iterators.next()...) {   // call “next” on each of 
>>> the iterators, put the results into a tuple named “values"
>>>       reachedEnd = true
>>>       return nil
>>>     }
>>> 
>>>     return values
>>>   }
>>> }
>>> 
>>> public struct ZipSequence<...Sequences : Sequence> : Sequence {
>>>   public typealias Iterator = ZipIterator<Sequences.Iterator...>   // get 
>>> the zip iterator with the iterator types of our Sequences
>>> 
>>>   var (...sequences): (Sequences...)    // zero or more stored properties, 
>>> one for each type in Sequences 
>>> 
>>>   // details ...
>>> }
>>> 
>>> Such a design could also work for function parameters, so we can pack 
>>> together multiple function arguments with different types, e.g.,
>>> 
>>> public func zip<... Sequences : SequenceType>(... sequences: Sequences...) 
>>>             -> ZipSequence<Sequences...> {
>>>   return ZipSequence(sequences...)
>>> }
>>> 
>>> Finally, this could tie into the discussions about a tuple “splat” 
>>> operator. For example:
>>> 
>>> func apply<... Args, Result>(fn: (Args...) -> Result,    // function taking 
>>> some number of arguments and producing Result
>>>                            args: (Args...)) -> Result {  // tuple of 
>>> arguments
>>>   return fn(args...)                                     // expand the 
>>> arguments in the tuple “args” into separate arguments
>>> }
>>> 
>>> 
>>> Extensions of structural types
>>> 
>>> Currently, only nominal types (classes, structs, enums, protocols) can be 
>>> extended. One could imagine extending structural types—particularly tuple 
>>> types—to allow them to, e.g., conform to protocols. For example, pulling 
>>> together variadic generics, parameterized extensions, and conditional 
>>> conformances, one could express “a tuple type is Equatable if all of its 
>>> element types are Equatable”:
>>> 
>>> extension<...Elements : Equatable> (Elements...) : Equatable {   // 
>>> extending the tuple type “(Elements…)” to be Equatable
>>> }
>>> 
>>> There are some natural bounds here: one would need to have actual 
>>> structural types. One would not be able to extend every type:
>>> 
>>> extension<T> T { // error: neither a structural nor a nominal type
>>> }
>>> 
>>> And before you think you’re cleverly making it possible to have a 
>>> conditional conformance that makes every type T that conforms to protocol P 
>>> also conform to protocol Q, see the section "Conditional conformances via 
>>> protocol extensions”, below:
>>> 
>>> extension<T : P> T : Q { // error: neither a structural nor a nominal type
>>> }
>>> 
>>> 
>>> Syntactic improvements
>>> 
>>> There are a number of potential improvements we could make to the generics 
>>> syntax. Such a list could go on for a very long time, so I’ll only 
>>> highlight some obvious ones that have been discussed by the Swift 
>>> developers.
>>> 
>>> *Default implementations in protocols
>>> 
>>> Currently, protocol members can never have implementations. We could allow 
>>> one to provide such implementations to be used as the default if a 
>>> conforming type does not supply an implementation, e.g.,
>>> 
>>> protocol Bag {
>>>   associatedtype Element : Equatable
>>>   func contains(element: Element) -> Bool
>>> 
>>>   func containsAll<S: Sequence where Sequence.Iterator.Element == 
>>> Element>(elements: S) -> Bool {
>>>     for x in elements {
>>>       if contains(x) { return true }
>>>     }
>>>     return false
>>>   }
>>> }
>>> 
>>> struct IntBag : Bag {
>>>   typealias Element = Int
>>>   func contains(element: Int) -> Bool { ... }
>>> 
>>>   // okay: containsAll requirement is satisfied by Bag’s default 
>>> implementation
>>> }
>>> 
>>> One can get this effect with protocol extensions today, hence the 
>>> classification of this feature as a (mostly) syntactic improvement:
>>> 
>>> protocol Bag {
>>>   associatedtype Element : Equatable
>>>   func contains(element: Element) -> Bool
>>> 
>>>   func containsAll<S: Sequence where Sequence.Iterator.Element == 
>>> Element>(elements: S) -> Bool
>>> }
>>> 
>>> extension Bag {
>>>   func containsAll<S: Sequence where Sequence.Iterator.Element == 
>>> Element>(elements: S) -> Bool {
>>>     for x in elements {
>>>       if contains(x) { return true }
>>>     }
>>>     return false
>>>   }
>>> }
>>> 
>>> 
>>> *Moving the where clause outside of the angle brackets
>>> 
>>> The “where” clause of generic functions comes very early in the 
>>> declaration, although it is generally of much less concern to the client 
>>> than the function parameters and result type that follow it. This is one of 
>>> the things that contributes to “angle bracket blindness”. For example, 
>>> consider the containsAll signature above:
>>> 
>>> func containsAll<S: Sequence where Sequence.Iterator.Element == 
>>> Element>(elements: S) -> Bool
>>> 
>>> One could move the “where” clause to the end of the signature, so that the 
>>> most important parts—name, generic parameter, parameters, result 
>>> type—precede it:
>>> 
>>> func containsAll<S: Sequence>(elements: S) -> Bool 
>>>        where Sequence.Iterator.Element == Element
>>> 
>>> 
>>> *Renaming “protocol<…>” to “Any<…>”.
>>> 
>>> The “protocol<…>” syntax is a bit of an oddity in Swift. It is used to 
>>> compose protocols together, mostly to create values of existential type, 
>>> e.g.,
>>> 
>>> var x: protocol<NSCoding, NSCopying>
>>> 
>>> It’s weird that it’s a type name that starts with a lowercase letter, and 
>>> most Swift developers probably never deal with this feature unless they 
>>> happen to look at the definition of Any:
>>> 
>>> typealias Any = protocol<>
>>> 
>>> “Any” might be a better name for this functionality. “Any” without brackets 
>>> could be a keyword for “any type”, and “Any” followed by brackets could 
>>> take the role of “protocol<>” today:
>>> 
>>> var x: Any<NSCoding, NSCopying>
>>> 
>>> That reads much better: “Any type that conforms to NSCoding and NSCopying”. 
>>> See the section "Generalized existentials” for additional features in this 
>>> space.
>>> 
>>> Maybe
>>> 
>>> There are a number of features that get discussed from time-to-time, while 
>>> they could fit into Swift’s generics system, it’s not clear that they 
>>> belong in Swift at all. The important question for any feature in this 
>>> category is not “can it be done” or “are there cool things we can express”, 
>>> but “how can everyday Swift developers benefit from the addition of such a 
>>> feature?”. Without strong motivating examples, none of these “maybes” will 
>>> move further along.
>>> 
>>> Dynamic dispatch for members of protocol extensions
>>> 
>>> Only the requirements of protocols currently use dynamic dispatch, which 
>>> can lead to surprises:
>>> 
>>> protocol P {
>>>   func foo()
>>> }
>>> 
>>> extension P {
>>>   func foo() { print(“P.foo()”)
>>>   func bar() { print(“P.bar()”)
>>> }
>>> 
>>> struct X : P {
>>>   func foo() { print(“X.foo()”)
>>>   func bar() { print(“X.bar()”)
>>> }
>>> 
>>> let x = X()
>>> x.foo() // X.foo()
>>> x.bar() // X.bar()
>>> 
>>> let p: P = X()
>>> p.foo() // X.foo()
>>> p.bar() // P.bar()
>>> 
>>> Swift could adopt a model where members of protocol extensions are 
>>> dynamically dispatched.
>>> 
>>> Named generic parameters
>>> 
>>> When specifying generic arguments for a generic type, the arguments are 
>>> always positional: Dictionary<String, Int> is a Dictionary whose Key type 
>>> is String and whose Value type is Int, by convention. One could permit the 
>>> arguments to be labeled, e.g.,
>>> 
>>> var d: Dictionary<Key: String, Value: Int>
>>> 
>>> Such a feature makes more sense if Swift gains default generic arguments, 
>>> because generic argument labels would allow one to skip defaulted arguments.
>>> 
>>> Generic value parameters
>>> 
>>> Currently, Swift’s generic parameters are always types. One could imagine 
>>> allowing generic parameters that are values, e.g.,
>>> 
>>> struct MultiArray<T, let Dimensions: Int> { // specify the number of 
>>> dimensions to the array
>>>   subscript (indices: Int...) -> T {
>>>     get {
>>>       require(indices.count == Dimensions)
>>>       // ...
>>>     }
>>> }
>>> 
>>> A suitably general feature might allow us to express fixed-length array or 
>>> vector types as a standard library component, and perhaps also allow one to 
>>> implement a useful dimensional analysis library. Tackling this feature 
>>> potentially means determining what it is for an expression to be a 
>>> “constant expression” and diving into dependent-typing, hence the “maybe”.
>>> 
>>> Higher-kinded types
>>> 
>>> Higher-kinded types allow one to express the relationship between two 
>>> different specializations of the same nominal type within a protocol. For 
>>> example, if we think of the Self type in a protocol as really being 
>>> “Self<T>”, it allows us to talk about the relationship between “Self<T>” 
>>> and “Self<U>” for some other type U. For example, it could allow the “map” 
>>> operation on a collection to return a collection of the same kind but with 
>>> a different operation, e.g.,
>>> 
>>> let intArray: Array<Int> = …
>>> intArray.map { String($0) } // produces Array<String>
>>> let intSet: Set<Int> = …
>>> intSet.map { String($0) }   // produces Set<String>
>>> 
>>> 
>>> Potential syntax borrowed from one thread on higher-kinded types 
>>> <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151214/002736.html>
>>>  uses ~= as a “similarity” constraint to describe a Functor protocol:
>>> 
>>> protocol Functor {
>>>   associatedtype A
>>>   func fmap<FB where FB ~= Self>(f: A -> FB.A) -> FB
>>> }
>>> 
>>> 
>>> Specifying type arguments for uses of generic functions
>>> 
>>> The type arguments of a generic function are always determined via type 
>>> inference. For example, given:
>>> 
>>> func f<T>(t: T)
>>> 
>>> one cannot directly specify T: either one calls “f” (and T is determined 
>>> via the argument’s type) or one uses “f” in a context where it is given a 
>>> particular function type (e.g., “let x: (Int) -> Void = f”  would infer T = 
>>> Int). We could permit explicit specialization here, e.g.,
>>> 
>>> let x = f<Int> // x has type (Int) -> Void
>>> 
>>> 
>>> Unlikely
>>> 
>>> Features in this category have been requested at various times, but they 
>>> don’t fit well with Swift’s generics system because they cause some part of 
>>> the model to become overly complicated, have unacceptable implementation 
>>> limitations, or overlap significantly with existing features.
>>> 
>>> Generic protocols
>>> 
>>> One of the most commonly requested features is the ability to parameterize 
>>> protocols themselves. For example, a protocol that indicates that the Self 
>>> type can be constructed from some specified type T:
>>> 
>>> protocol ConstructibleFromValue<T> {
>>>   init(_ value: T)
>>> }
>>> 
>>> Implicit in this feature is the ability for a given type to conform to the 
>>> protocol in two different ways. A “Real” type might be constructible from 
>>> both Float and Double, e.g.,
>>> 
>>> struct Real { … }
>>> extension Real : ConstructibleFrom<Float> {
>>>   init(_ value: Float) { … }
>>> }
>>> extension Real : ConstructibleFrom<Double> {
>>>   init(_ value: Double) { … }
>>> }
>>> 
>>> Most of the requests for this feature actually want a different feature. 
>>> They tend to use a parameterized Sequence as an example, e.g.,
>>> 
>>> protocol Sequence<Element> { … }
>>> 
>>> func foo(strings: Sequence<String>) {  /// works on any sequence containing 
>>> Strings
>>>   // ...
>>> }
>>> 
>>> The actual requested feature here   is the ability to say “Any type that 
>>> conforms to Sequence whose Element type is String”, which is covered by the 
>>> section on “Generalized existentials”, below.
>>> 
>>> More importantly, modeling Sequence with generic parameters rather than 
>>> associated types is tantalizing but wrong: you don’t want a type conforming 
>>> to Sequence in multiple ways, or (among other things) your for..in loops 
>>> stop working, and you lose the ability to dynamically cast down to an 
>>> existential “Sequence” without binding the Element type (again, see 
>>> “Generalized existentials”). Use cases similar to the 
>>> ConstructibleFromValue protocol above seem too few to justify the potential 
>>> for confusion between associated types and generic parameters of protocols; 
>>> we’re better off not having the latter.
>>> 
>>> 
>>> Private conformances 
>>> 
>>> Right now, a protocol conformance can be no less visible than the minimum 
>>> of the conforming type’s access and the protocol’s access. Therefore, a 
>>> public type conforming to a public protocol must provide the conformance 
>>> publicly. One could imagine removing that restriction, so that one could 
>>> introduce a private conformance:
>>> 
>>> public protocol P { }
>>> public struct X { }
>>> extension X : internal P { … } // X conforms to P, but only within this 
>>> module
>>> 
>>> The main problem with private conformances is the interaction with dynamic 
>>> casting. If I have this code:
>>> 
>>> func foo(value: Any) {
>>>   if let x = value as? P { print(“P”) }
>>> }
>>> 
>>> foo(X())
>>> 
>>> Under what circumstances should it print “P”? If foo() is defined within 
>>> the same module as the conformance of X to P? If the call is defined within 
>>> the same module as the conformance of X to P? Never? Either of the first 
>>> two answers requires significant complications in the dynamic casting 
>>> infrastructure to take into account the module in which a particular 
>>> dynamic cast occurred (the first option) or where an existential was formed 
>>> (the second option), while the third answer breaks the link between the 
>>> static and dynamic type systems—none of which is an acceptable result.
>>> 
>>> Conditional conformances via protocol extensions
>>> 
>>> We often get requests to make a protocol conform to another protocol. This 
>>> is, effectively, the expansion of the notion of “Conditional conformances” 
>>> to protocol extensions. For example:
>>> 
>>> protocol P {
>>>   func foo()
>>> }
>>> 
>>> protocol Q {
>>>   func bar()
>>> }
>>> 
>>> extension Q : P { // every type that conforms to Q also conforms to P
>>>   func foo() {    // implement “foo” requirement in terms of “bar"
>>>     bar()
>>>   }
>>> }
>>> 
>>> func f<T: P>(t: T) { … }
>>> 
>>> struct X : Q {
>>>   func bar() { … }
>>> }
>>> 
>>> f(X()) // okay: X conforms to P through the conformance of Q to P
>>> 
>>> This is an extremely powerful feature: is allows one to map the 
>>> abstractions of one domain into another domain (e.g., every Matrix is a 
>>> Graph). However, similar to private conformances, it puts a major burden on 
>>> the dynamic-casting runtime to chase down arbitrarily long and potentially 
>>> cyclic chains of conformances, which makes efficient implementation nearly 
>>> impossible.
>>> 
>>> Potential removals
>>> 
>>> The generics system doesn’t seem like a good candidate for a reduction in 
>>> scope; most of its features do get used fairly pervasively in the standard 
>>> library, and few feel overly anachronistic. However...
>>> 
>>> Associated type inference
>>> 
>>> Associated type inference is the process by which we infer the type 
>>> bindings for associated types from other requirements. For example:
>>> 
>>> protocol IteratorProtocol {
>>>   associatedtype Element
>>>   mutating func next() -> Element?
>>> }
>>> 
>>> struct IntIterator : IteratorProtocol {
>>>   mutating func next() -> Int? { … }  // use this to infer Element = Int
>>> }
>>> 
>>> Associated type inference is a useful feature. It’s used throughout the 
>>> standard library, and it helps keep associated types less visible to types 
>>> that simply want to conform to a protocol. On the other hand, associated 
>>> type inference is the only place in Swift where we have a global type 
>>> inference problem: it has historically been a major source of bugs, and 
>>> implementing it fully and correctly requires a drastically different 
>>> architecture to the type checker. Is the value of this feature worth 
>>> keeping global type inference in the Swift language, when we have 
>>> deliberatively avoided global type inference elsewhere in the language?
>>> 
>>> 
>>> Existentials
>>> 
>>> Existentials aren’t really generics per se, but the two systems are closely 
>>> intertwined due to their mutable dependence on protocols.
>>> 
>>> *Generalized existentials
>>> 
>>> The restrictions on existential types came from an implementation 
>>> limitation, but it is reasonable to allow a value of protocol type even 
>>> when the protocol has Self constraints or associated types. For example, 
>>> consider IteratorProtocol again and how it could be used as an existential:
>>> 
>>> protocol IteratorProtocol {
>>>   associatedtype Element
>>>   mutating func next() -> Element?
>>> }
>>> 
>>> let it: IteratorProtocol = …
>>> it.next()   // if this is permitted, it could return an “Any?”, i.e., the 
>>> existential that wraps the actual element
>>> 
>>> Additionally, it is reasonable to want to constrain the associated types of 
>>> an existential, e.g., “a Sequence whose element type is String” could be 
>>> expressed by putting a where clause into “protocol<…>” or “Any<…>” (per 
>>> “Renaming protocol<…> to Any<…>”):
>>> 
>>> let strings: Any<Sequence where .Iterator.Element == String> = [“a”, “b”, 
>>> “c”]
>>> 
>>> The leading “.” indicates that we’re talking about the dynamic type, i.e., 
>>> the “Self” type that’s conforming to the Sequence protocol. There’s no 
>>> reason why we cannot support arbitrary “where” clauses within the “Any<…>”. 
>>> This very-general syntax is a bit unwieldy, but common cases can easily be 
>>> wrapped up in a generic typealias (see the section “Generic typealiases” 
>>> above):
>>> 
>>> typealias AnySequence<Element> = Any<Sequence where .Iterator.Element == 
>>> Element>
>>> let strings: AnySequence<String> = [“a”, “b”, “c”]
>>> 
>>> 
>>> Opening existentials
>>> 
>>> Generalized existentials as described above will still have trouble with 
>>> protocol requirements that involve Self or associated types in function 
>>> parameters. For example, let’s try to use Equatable as an existential:
>>> 
>>> protocol Equatable {
>>>   func ==(lhs: Self, rhs: Self) -> Bool
>>>   func !=(lhs: Self, rhs: Self) -> Bool
>>> }
>>> 
>>> let e1: Equatable = …
>>> let e2: Equatable = …
>>> if e1 == e2 { … } // error: e1 and e2 don’t necessarily have the same 
>>> dynamic type
>>> 
>>> One explicit way to allow such operations in a type-safe manner is to 
>>> introduce an “open existential” operation of some sort, which extracts and 
>>> gives a name to the dynamic type stored inside an existential. For example:
>>> 
>>>      
>>> if let storedInE1 = e1 openas T {     // T is a the type of storedInE1, a 
>>> copy of the value stored in e1
>>>   if let storedInE2 = e2 as? T {      // is e2 also a T?
>>>     if storedInE1 == storedInE2 { … } // okay: storedInT1 and storedInE2 
>>> are both of type T, which we know is Equatable
>>>   }
>>> }
>>> 
>>> Thoughts?
>>> 
>>>     - Doug
>>> 
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to