Hi everybody,

I added details suggested by Xiaodi and opened a pull request. Any last minute 
modifications before it gets merged in?

https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md

Typealiases in protocols and protocol extensions

Proposal: SE-XXXX 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md>
Authors: David Hart <https://github.com/hartbit>, Doug Gregor 
<https://github.com/DougGregor>
Status: TBD
Review manager: TBD
 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md#introduction>Introduction

This proposal is from the Generics Manifesto 
<https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md> and 
brings the typealias keyword back into protocols for type aliasing.

 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md#motivation>Motivation

In Swift versions prior to 2.2, the typealias keyword was used outside of 
protocols to declare type aliases and in protocols to declare associated types. 
Since SE-0011 
<https://github.com/apple/swift-evolution/blob/master/proposals/0011-replace-typealias-associated.md>
 and Swift 2.2, associated type now use the associatedtypekeyword and typealias 
is available for implementing true associated type aliases. 

 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md#proposed-solution>Proposed
 solution

The solution allows the creation of associated type aliases. Here is an example 
from the standard library:

protocol Sequence {
  associatedtype Iterator : IteratorProtocol
  typealias Element = Iterator.Element
}
The example above shows how this simplifies referencing indirect associated 
types:

func sum<T: Sequence where T.Element == Int>(sequence: T) -> Int {
    return sequence.reduce(0, combine: +)
}
Allowing typealias in protocol extensions also allows extensions to use aliases 
to simplify code that the protocol did not originally propose:

extension Sequence {
    typealias Element = Iterator.Element

    func concat(other: Self) -> [Element] {
        return Array<Element>(self) + Array<Element>(other)
    }
}
 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md#detailed-design>Detailed
 design

The following grammar rules needs to be added:

protocol-member-declaration → protocol-typealias-declaration

protocol-typealias-declaration → typealias-declaration

 
<https://github.com/hartbit/swift-evolution/blob/a1b883132588bd0ceff5e5c9787bcef140f6674a/proposals/XXXX-typealiases-in-protocols.md#impact-on-existing-code>Impact
 on existing code

This will initially have no impact on existing code, but will probably require 
improving the Fix-It that was created for migrating typealias to associatedtype 
in Swift 2.2.

But once typealias starts being used inside protocols, especially in the 
Standard Library, name clashes might start cropping up between the type aliases 
and associated types. For example:

protocol Sequence {
    typealias Element = Iterator.Element // once this is added
}

protocol MySequence: Sequence {
    associatedtype Element // MySequence.Element is ambiguous
}
But there is no reason that those name clashes behave differently than current 
clashes between associated types:

protocol Foo {
    associatedtype Inner: IntegerType
    func foo(inner: Inner)
}

protocol Bar {
    associatedtype Inner: FloatingPointType
    var inner: Inner { get }
}

struct FooBarImpl: Foo, Bar { // error: Type ‘FooBarImpl’ does not conform to 
protocol ‘Bar'
    func foo(inner: Int) {}
    var inner: Float
}


> On 09 May 2016, at 22:18, Xiaodi Wu <[email protected]> wrote:
> 
> Sorry--I'm not at all saying that I think there's a problem. As you asked, I 
> attempted to supply a contrived use case for a typealias declared in a 
> protocol having a more restricted scope than the protocol itself. I was 
> asking if it would be supported as part of your proposal.
> 
> 
> On Mon, May 9, 2016 at 3:11 PM, David Hart <[email protected] 
> <mailto:[email protected]>> wrote:
> I don’t see a problem with your example. Because the typealias is 
> fileprivate, it doesn’t exist as far as MyUsefulType is concerned. The same 
> way the following works:
> 
> ```
> class Base {
>     private typealias Foo = Int
>     func foo() -> Int {
>         return Foo()
>     }
> }
> ```
> 
> Other file:
> 
> ```
> class Derived: Base {
>     typealias Foo = String
>     func bar() -> String {
>         return "Hello \(foo())"
>     }
> }
> ```
> 
>> On 09 May 2016, at 10:37, Xiaodi Wu <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>> On Mon, May 9, 2016 at 2:31 AM, David Hart <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> On 09 May 2016, at 09:16, Xiaodi Wu <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> One more thought here:
>>> 
>>> It goes a long way to say "typealiases in protocols are to have the same 
>>> semantics as aliases outside protocols." I'm inclined to agree on that, but 
>>> I haven't thought it totally through.
>>> 
>>> Now, I can have private typealiases outside protocols. Could I have private 
>>> typealiases inside protocols? They'd be handy for referencing types while 
>>> implementing default methods in protocol extensions and whatnot without 
>>> worrying about collisions with typealiases in conforming types…
>> 
>> Sounds like it should be allowed. I’ll add something about it in the 
>> proposal. Could you give an example of what you mean by "without worrying 
>> about collisions with typealiases in conforming types…”?
>> 
>> 
>> I wonder if this takes things in an, um, interesting direction. Suppose I 
>> could have this (a contrived example--it may fall apart on further study):
>> 
>> ```
>> protocol MyUsefulProtocol {
>>   associatedtype Storage : Collection
>>   fileprivate typealias UniqueIdentifier = Storage.Index
>>   func doUsefulThing() -> Storage
>> }
>> 
>> extension MyUsefulProtocol {
>>   func doUsefulThing() -> Storage {
>>     // do something useful in this default implementation
>>     // use UniqueIdentifier internally here and only here
>>   }
>> }
>> ```
>> 
>> In a different file:
>> 
>> ```
>> struct MyUsefulType<A : Hashable, B> : MyUsefulProtocol {
>>   /* I could do this if I wanted:
>>   typealias UniqueIdentifier = A
>>   
>>   More importantly, I could retroactively conform MyUsefulType
>>   to MyUsefulProtocol even if they happen to have clashing
>>   typealiases, which is great because the typealias in
>>   MyUsefulProtocol is used for clarity and convenience inside
>>   the default implementation and is irrelevant here
>>   */
>>   func doUsefulThing() -> Dictionary<A, B> {
>>     // do something useful but different
>>     // from the default implementation
>>   }
>> }
>> ```
>> 
>> I wonder, though, if this is to be allowed, whether much the same could be 
>> achieved by instead allowing associatedtype declarations to have default 
>> values (for example: `associatedtype UniqueIdentifier : Equatable = 
>> Storage.Index`), at which point we might be one step away from going full 
>> circle and eliminating the distinction between associatedtypes and 
>> typealiases once again.
>> 
>> 
>>> On Mon, May 9, 2016 at 01:52 David Hart <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> I understand that name clashing in those instances is important to discuss, 
>>> but I still think it is slightly orthogonal to the proposal. Let me try to 
>>> explain why.
>>> 
>>> If typealises in protocols are to have the same semantics as alises outside 
>>> protocols (as I think they should), then they don’t change anything about 
>>> the rules of collision. For example, the problem already exists today with 
>>> associated types:
>>> 
>>> protocol Foo {
>>>     associatedtype Inner: IntegerType
>>>     func foo(inner: Inner)
>>> }
>>> 
>>> protocol Bar {
>>>     associatedtype Inner: FloatingPointType
>>>     var inner: Inner { get }
>>> }
>>> 
>>> struct FooBarImpl: Foo, Bar { // error: Type ‘FooBarImpl’ does not conform 
>>> to protocol ‘Bar'
>>>     func foo(inner: Int) {}
>>>     var inner: Float
>>> }
>>> 
>>> Type aliasing would not change anything about the fact that those 
>>> collisions already exists in the language and are not very well handled: 
>>> either they are meant to be forbidden but in that case we need better 
>>> diagnostics, or we want to have a way to work around them. Perhaps you’d 
>>> like to start a discussion around fixing that ?
>>> 
>>>> On 09 May 2016, at 08:06, Xiaodi Wu <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>> I see your point that nothing breaks in the stdlib with your proposal 
>>>> alone. It's undeniably true--by construction!--that a purely additive 
>>>> feature, if never used, will not cause problems.
>>>> 
>>>> That said, since the time that this feature was outlined in Doug's 
>>>> manifesto, I have been wondering how clashes such as the examples in my 
>>>> previous email are to be handled--i.e. what the rules of the language are 
>>>> to be--which I think is certainly germane to your proposal. Can a 
>>>> conforming type override a protocol typealias? Can a type conform to two 
>>>> protocols with conflicting typealiases if all requirements are otherwise 
>>>> satisfied? Surely, these merit discussion in your proposal.
>>>> 
>>>> On Mon, May 9, 2016 at 12:48 AM David Hart <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> Hello Xiaodi,
>>>> 
>>>> What I mean by there is no impact on existing code is that the language 
>>>> change has no impact. Of course, if the Standard Library then declares a 
>>>> typealias Element in Sequence, it will clash with code which has declared 
>>>> an Element typealias in sub-protocols, but that is separate from the 
>>>> proposal.
>>>> 
>>>>> On 09 May 2016, at 07:28, Xiaodi Wu <[email protected] 
>>>>> <mailto:[email protected]>> wrote:
>>>>> 
>>>>> If the protocol Sequence has typealias Element, does that mean I also 
>>>>> have MyConformingSequence.Element?
>>>>> 
>>>>> If so, I think there is a potential impact on existing code not 
>>>>> mentioned. Suppose MyConformingSequence already (unwisely) declares 
>>>>> typealias Element. Now, what happens when I try to migrate my code to 
>>>>> your proposed version of Swift?
>>>>> 
>>>>> This is a toy example, of course. More generally, though, I wonder about 
>>>>> this question:
>>>>> 
>>>>> Suppose two protocols A and B each declare typealias Element. These 
>>>>> typealiases are, as you proposed, intended to simplify referencing 
>>>>> indirect associated types. But are they themselves considered protocol 
>>>>> requirements?
>>>>> 
>>>>> I ask because, suppose I want to conform type T to A and B. I implement 
>>>>> all the required methods and properties for such conformance. I declare 
>>>>> the appropriate typealiases for the associatedtypes declared in both 
>>>>> protocols. But, if A.Element and B.Element are incompatible with each 
>>>>> other, it is nonetheless impossible to conform T to both A and B? If it's 
>>>>> forbidden, isn't that kind of a bummer, since what's getting in the way 
>>>>> is a naming clash arising from a facility intended to simplify the naming 
>>>>> of things rather than provide for new functionality? If it's permitted, 
>>>>> what is T.Element? Some clarity here would be nice.
>>>>> On Sun, May 8, 2016 at 6:17 PM David Hart via swift-evolution 
>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>> Hello,
>>>>> 
>>>>> I’ve come again with another proposal directly from the Generics 
>>>>> Manifesto. Please let me know if it needs any modifications before 
>>>>> sending the pull request.
>>>>> 
>>>>> Typealiases in protocols and protocol extensions
>>>>> 
>>>>> Proposal: SE-XXXX 
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md>
>>>>> Authors: David Hart <https://github.com/hartbit>, Doug Gregor 
>>>>> <https://github.com/DougGregor>
>>>>> Status: TBD
>>>>> Review manager: TBD
>>>>>  
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md#introduction>Introduction
>>>>> 
>>>>> This proposal is from the Generics Manifesto 
>>>>> <https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md> 
>>>>> and brings the typealias keyword back into protocols for type aliasing.
>>>>> 
>>>>>  
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md#motivation>Motivation
>>>>> 
>>>>> In Swift versions prior to 2.2, the typelias keyword was used outside of 
>>>>> protocols to declare type aliases and in protocols to declare associated 
>>>>> types. Since SE-0011 
>>>>> <https://github.com/apple/swift-evolution/blob/master/proposals/0011-replace-typealias-associated.md>
>>>>>  and Swift 2.2, associated type now use the associatedtype keyword and 
>>>>> typelias is available for implementing true associated type aliases. 
>>>>> 
>>>>>  
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md#proposed-solution>Proposed
>>>>>  solution
>>>>> 
>>>>> The solution allows the creation of associated type aliases. Here is an 
>>>>> example from the standard library:
>>>>> 
>>>>> protocol Sequence {
>>>>>   associatedtype Iterator : IteratorProtocol
>>>>>   typealias Element = Iterator.Element
>>>>> }
>>>>> The example above shows how this simplifies referencing indirect 
>>>>> associated types:
>>>>> 
>>>>> func sum<T: Sequence where T.Element == Int>(sequence: T) -> Int {
>>>>>     return sequence.reduce(0, combine: +)
>>>>> }
>>>>>  
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md#detailed-design>Detailed
>>>>>  design
>>>>> 
>>>>> The following grammar rules needs to be added:
>>>>> 
>>>>> protocol-member-declaration → protocol-typealias-declaration
>>>>> 
>>>>> protocol-typealias-declaration → typealias-declaration
>>>>> 
>>>>>  
>>>>> <https://github.com/hartbit/swift-evolution/blob/typealiases-in-protocols/proposals/XXXX-typealiases-in-protocols.md#impact-on-existing-code>Impact
>>>>>  on existing code
>>>>> 
>>>>> This will have no impact on existing code, but will probably require 
>>>>> improving the Fix-It that was created for migrating typealias to 
>>>>> associatedtype in Swift 2.2.
>>>>> _______________________________________________
>>>>> 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

Reply via email to