Sorry, I misunderstood that you meant that the version of Concrete same-type 
requirement that does not introduce new syntax could be sent through as a bug 
request. It’s now done:

[SR-1447] Concrete same-type requirements 
<https://bugs.swift.org/browse/SR-1447>

> On 08 May 2016, at 23:17, David Hart via swift-evolution 
> <[email protected]> wrote:
> 
> 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 <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> 
>> 
>> Sent from my iPhone
>> 
>> On May 2, 2016, at 3:58 PM, David Hart <[email protected] 
>> <mailto:[email protected]>> 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 
>>>> <[email protected] <mailto:[email protected]>> 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
>>>> [email protected] <mailto:[email protected]>
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution 
>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution>
>>> 
> 
> _______________________________________________
> swift-evolution mailing list
> [email protected]
> https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to