Mark protocol methods with their protocol

I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.

Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).

// generates thunks to members of this extension in the base type; 
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re inside MyComplexDataType
        // No need to pollute internal API with conformance implementation details.
        // Also, we get errors about non-conformance where we want them — where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}
···

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm not sure I understand. What compiler or language support is missing for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com <mailto:raziel.im+swift-evo@gmail.com>> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

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

Yes, because “implement” doesn’t say anything. It would need to be “implements <ProtocolName>” to be useful to a person or to the type-checker.

At that point, why not just say MyProtocol.aVariable? It feels more natural IMO.

And then the rest kind of snowballs from there...

···

On 21 Sep 2016, at 00:08, Vladimir.S <svabox@gmail.com> wrote:

On 21.09.2016 0:28, Karl via swift-evolution wrote:

I don't understand. Do you feel that this:

class MyClass : MyProto {
   var MyProto.aVariable : Int
   func MyProto.aFunction() { … }
}

better than this:

class MyClass : MyProto {
   implement var aVariable : Int
   implement func aFunction() { … }
}

?

I’m using String as an example of where this issue of conformance conflicts crops up in the standard library. Ideally, String (or any data type) should be able to conform to protocols whose requirements have conflicting names.
Currently, in order to work around this limitation, you have to delegate the conformance to a supporting type. This is more complicated to write and maintain, and pollutes your internal API. String gives us an example of this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a supporting type instead of directly inside the data-type (String). As an ABI consideration, we should scope all protocol members to their protocols. This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re currently in-between two ideas of what protocols should be - they are explicit but their conformances are resolved by name only and can overlap without warning.

···

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Sorry, I'm still not sure I understand what you're getting at about this. How would String conforming to Collection multiple times simplify or improve the implementation of String? Or are you arguing it would be better for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.

Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).

// generates thunks to members of this extension in the base type; 
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re inside MyComplexDataType
        // No need to pollute internal API with conformance implementation details.
        // Also, we get errors about non-conformance where we want them — where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I'm not sure I understand. What compiler or language support is missing for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com <mailto:raziel.im+swift-evo@gmail.com>> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

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

I’ve explained it so many times, do you really not understand it?

Basically, protocols are explicit things. They are **not** things that you just “discover” about types at all. We have protocols with no members (“marker protocols”) which are basically used to tag certain types with no other guarantees. That is the important difference between protocols in Swift and in Objective-C. Even if you have implementations for every requirement, if you never explicitly declared conformance you don’t conform. Period.

However, the requirements themselves don’t need to be explicitly marked-up. They just get automatically assigned by the compiler; maybe my property named “count” doesn’t mean the same thing as Collection’s “count”?

I’ve written a lot trying to explain this; please tell me what you don’t understand. To summarise (again):

- Members which satisfy a protocol requirement will have to be explicit about which protocol they belong to
——> They will no longer be automatically assigned as the witness for a protocol requirement

- Members which satisfy a protocol requirement will have the protocol name in their symbolic names (e.g. MyType.someFunction() —> MyType.AProtocol.someFunction())
——> this will allow the same type to conform to protocols with overlapping names, free protocol designers from naming constraints, and reduce the need for “helper structs” to represent alternate views of the same data.
——> Extensions which declare conformance have to satisfy all of their requirements explicitly - by implementing, forwarding to other functions, stored properties or other objects. We can have a shorthand to make this easy.

IMO, we definitely need to solve the overlapping naming problem. If we explicitly assign protocol methods to protocols (as the thread was originally about), this falls out of it.

···

On 21 Sep 2016, at 01:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This was the conversation we were having in the other thread. Perhaps I'm still not understanding something, but I'm not convinced that this feature is an improvement.

Currently, protocols represent a declaration that you have discovered that your type has certain semantics and guarantees a certain API, and you declare that fulfillment "by name only," just as you invoke members "by name only"; unintentional failure to fulfill the contract is a compile-time error. The status quo is precisely my idea of what protocols should be. What are the two ideas you have about them?
On Tue, Sep 20, 2016 at 18:02 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m using String as an example of where this issue of conformance conflicts crops up in the standard library. Ideally, String (or any data type) should be able to conform to protocols whose requirements have conflicting names.
Currently, in order to work around this limitation, you have to delegate the conformance to a supporting type. This is more complicated to write and maintain, and pollutes your internal API. String gives us an example of this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a supporting type instead of directly inside the data-type (String). As an ABI consideration, we should scope all protocol members to their protocols. This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re currently in-between two ideas of what protocols should be - they are explicit but their conformances are resolved by name only and can overlap without warning.

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Sorry, I'm still not sure I understand what you're getting at about this. How would String conforming to Collection multiple times simplify or improve the implementation of String? Or are you arguing it would be better for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.

Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).

// generates thunks to members of this extension in the base type; 
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re inside MyComplexDataType
        // No need to pollute internal API with conformance implementation details.
        // Also, we get errors about non-conformance where we want them — where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I'm not sure I understand. What compiler or language support is missing for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com <mailto:raziel.im+swift-evo@gmail.com>> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

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

I would like to make it a requirement if not inside a protocol extension which declares a conformance, and actually build the protocol name in to the member in an ABI-breaking way. We could make it additive by generating forwarding thunks from the old symbols to the new ones, but it would be better if we could just solve the overlapping-members problem before then.

That would mean you never get collisions between protocol members. There’s loads of amazing stuff we can do with that ability, and ways we can extend it to reduce a lot of boilerplate that occurs when you want to have multiple representations of the same data (String is just an example).

I don’t really care about the syntax we need to make it liveable. We could automatically insert the protocol names for unambiguous members at call-site, or something else.

This thread was originally about making the *syntax* a requirement; I agree with that, and I would actually take it one (or several) steps further, solving other problems along the way.

···

On 22 Sep 2016, at 06:46, Russ Bishop <xenadu@gmail.com> wrote:

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
  var aVariable : Int
  func aFunction()
}
class MyClass : MyProto {
  var MyProto.aVariable : Int
  func MyProto.aFunction() { … }
}

...

CC-ing Dave A, to understand better if this fits with the vision of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should be
to define the entity in an extension that also adds conformance to P.
If that's inadequate indication in some way we should find a way to
enhance it. I wouldn't mind the notation above, but only as a fallback,
not a reuquirement.

--
-Dave
_______________________________________________

Indeed this is exactly how C# handles Interfaces (protocols). The default is the exact same way Swift works - by matching names. If there is a collision you specify Protocol.memberName. Its simple and in the years I was writing C# code it was flexible enough to cover most reasonable scenarios, without adding a bunch of boilerplate.

Russ

I think the best way is to prefix the member name with the protocol,
e.g:

protocol MyProto { var aVariable : Int func aFunction() } class
MyClass : MyProto { var MyProto.aVariable : Int func
MyProto.aFunction() { … } }

...

CC-ing Dave A, to understand better if this fits with the vision of
protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should
be to define the entity in an extension that also adds conformance to
P. If that's inadequate indication in some way we should find a way
to enhance it. I wouldn't mind the notation above, but only as a
fallback, not a reuquirement.

-- -Dave _______________________________________________

Indeed this is exactly how C# handles Interfaces (protocols). The

Can C#'s interface(protocol) have default implementations for its requirements like in Swift?

···

On 22.09.2016 7:46, Russ Bishop via swift-evolution wrote:

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution >> <swift-evolution@swift.org> wrote:
on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

default is the exact same way Swift works - by matching names. If there
is a collision you specify Protocol.memberName. Its simple and in the
years I was writing C# code it was flexible enough to cover most
reasonable scenarios, without adding a bunch of boilerplate.

Russ

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

Sorry, I'm still not sure I understand what you're getting at about this.
How would String conforming to Collection multiple times simplify or
improve the implementation of String? Or are you arguing it would be better
for users of String? If so, how?

···

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com> wrote:

I’m not saying vital support is missing, just that it is more awkward.
String doesn’t conform to collection, String.UTF8View does; so if you
change some implementation detail (in StringCore, because that’s where they
live for String), you get the error popping up somewhere other than the
place you just changed. That’s what I mean when I say “language support”.
If you do what StringCore does, and you’re changing stuff which is
ultimately going to be used to conform to, say, Collection, you have to
build distance between the implementation and the (only) conformance it is
used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements
“InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a
name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave
inside the type, otherwise we’d need to expose a bunch of implementation
details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return
InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to
Collection multiple times with different indexes and results). It’s a lot
of work to maintain, especially if you have evolving protocols that are
conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same
time, since we’re now being explicit about which protocol requirement is
satisfied where - we should also be able to delegate our conformance,
telling the compiler to dispatch any unimplemented methods to another
object. For example, lets say you want to wrap a Collection and observe
mutations to it; you might override replaceSubrange(), but every other
method (such as count, index(after:)… all the rest) is just a forwarding
function.

Interestingly, we could do this safely (from a code legibility
perspective) if we say that every scope which adds a conformance must
completely satisfy its requirements, which we would more reasonably be able
to require if we made this change (so your internal functions can still be
wherever you like, but they won’t automatically satisfy a protocol
requirement if they happen to have the same name). Then we could reasonably
say that if you add an extension which adds a conformance to, say,
Collection, you have to tell us where to find every one of its
requirements. That’s where we could put the forwarding syntax for
retroactive modelling. Stored properties can’t be defined in extensions, so
if you want to back an implementation with one, you’ll need to make its
conformance explicit in the main body (or we loosen that to at least
extensions in the same file).

// generates thunks to members of this extension in the base type;
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be
used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re
inside MyComplexDataType
        // No need to pollute internal API with conformance implementation
details.
        // Also, we get errors about non-conformance where we want them —
where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm not sure I understand. What compiler or language support is missing
for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution < > swift-evolution@swift.org> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution < >> swift-evolution@swift.org> wrote:

I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a
protocol, that means it has all the members specified in the protocol. The
protocol conformance simply codifies a fact about the type itself: namely
that all those members are present.

In this model, any keyword such as `implements` on each conforming member
would introduce substantial boilerplate for negligible gain. The purpose of
a protocol is to communicate that certain members are available, not to
make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there
is actual implementation being inherited. A conforming type may choose to
roll its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define
(or redefine!) default implementations for members of that other protocol.
This can create “inheritance chains” of protocol default implementations. I
think there is value in being able to refer to (and call) the inherited
default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a
protocol is in large part merely a convenience: a courtesy so that each
conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves
some attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put
forth, I come down firmly on the side of no keyword for protocol
conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

As I mentioned above, I agree that better diagnostics for near-misses
are necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < >>> swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be
clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to
avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point,
IMO.
>>>
>>> However, I think it could be improved in one key respect where
previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to
change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some
*other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in
this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will
save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this
is
> not the correct error, since S in fact *tries* to conform to P, but
it has
> a mistake in a method signature. This misleads us as to the true
nature of
> the problem, and if S has enough members in it that we fail to spot
the
> existing foo(), we might solve the problem by reimplementing foo(),
and
> leaving the original foo() as dangling dead code. Having an
‘implement’
> keyword on the existing foo() function would change the compiler
error to
> let us know that we have an existing foo() that is incorrectly
declared.
>
> In addition, ‘implement’ can help us when the declaration in question
*is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword,
because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to
the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite
a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g.
“extension MyClass.MyInternalClass”). It will be easy for autocompletion to
provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function
called `aFunction()`? What if the same name satisfies 2 protocols, which do
you write?

The way to solve all of the problems in a consistent way is to make the
function actually called “MyProto.aFunction”, and for it to be a separate
function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have
some complex data structure and it has its own API, but I want people to be
able to view it as a Collection. By conforming to Collection, I reserve
lots of keywords and indexing operations which I now can’t use in my own
API. Maybe I’m just providing Collection as a convenience to work with
generic algorithms, but my own API has more efficient semantics for some
operations. We’re relegated to using less-obvious and legible names in
order to avoid conflicts.

We have a way to work around this, which String uses - create a struct
which references your object and calls internal methods such as
“_collection_count” so you can have separate interfaces. This adds up to
quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing
manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and
defines some internal functions to support it.

The String views could then be made in to protocols on String, turning
“UTF8View” in to “UTF8Representable”, and opening up algorithms which can
work on generic sequences of UTF8 bytes. I think that’s pretty cool, and
could open up better integration with other types which are (for example)
UTF8Representable — for example a stream of UTF8 bytes (depending on how
flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as
others here have written. This isn’t like Objective-C where anything that
has the correctly-named methods conforms. Protocol conformances are
completely explicit, and in fact we have empty protocols (“marker
protocols”) for exactly that purpose. I think it is consistent that we make
every member of a conformance specify which protocol it belongs to, and to
have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of
protocols

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

This was the conversation we were having in the other thread. Perhaps I'm
still not understanding something, but I'm not convinced that this feature
is an improvement.

Currently, protocols represent a declaration that you have discovered that
your type has certain semantics and guarantees a certain API, and you
declare that fulfillment "by name only," just as you invoke members "by
name only"; unintentional failure to fulfill the contract is a compile-time
error. The status quo is precisely my idea of what protocols should be.
What are the two ideas you have about them?

···

On Tue, Sep 20, 2016 at 18:02 Karl <razielim@gmail.com> wrote:

I’m using String as an example of where this issue of conformance
conflicts crops up in the standard library. Ideally, String (or any data
type) should be able to conform to protocols whose requirements have
conflicting names.
Currently, in order to work around this limitation, you have to delegate
the conformance to a supporting type. This is more complicated to write and
maintain, and pollutes your internal API. String gives us an example of
this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a
supporting type instead of directly inside the data-type (String). As an
ABI consideration, we should scope all protocol members to their protocols.
This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re
currently in-between two ideas of what protocols should be - they are
explicit but their conformances are resolved by name only and can overlap
without warning.

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Sorry, I'm still not sure I understand what you're getting at about this.
How would String conforming to Collection multiple times simplify or
improve the implementation of String? Or are you arguing it would be better
for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com> wrote:

I’m not saying vital support is missing, just that it is more awkward.
String doesn’t conform to collection, String.UTF8View does; so if you
change some implementation detail (in StringCore, because that’s where they
live for String), you get the error popping up somewhere other than the
place you just changed. That’s what I mean when I say “language support”.
If you do what StringCore does, and you’re changing stuff which is
ultimately going to be used to conform to, say, Collection, you have to
build distance between the implementation and the (only) conformance it is
used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements
“InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause
a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave
inside the type, otherwise we’d need to expose a bunch of implementation
details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return
InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to
Collection multiple times with different indexes and results). It’s a lot
of work to maintain, especially if you have evolving protocols that are
conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same
time, since we’re now being explicit about which protocol requirement is
satisfied where - we should also be able to delegate our conformance,
telling the compiler to dispatch any unimplemented methods to another
object. For example, lets say you want to wrap a Collection and observe
mutations to it; you might override replaceSubrange(), but every other
method (such as count, index(after:)… all the rest) is just a forwarding
function.

Interestingly, we could do this safely (from a code legibility
perspective) if we say that every scope which adds a conformance must
completely satisfy its requirements, which we would more reasonably be able
to require if we made this change (so your internal functions can still be
wherever you like, but they won’t automatically satisfy a protocol
requirement if they happen to have the same name). Then we could reasonably
say that if you add an extension which adds a conformance to, say,
Collection, you have to tell us where to find every one of its
requirements. That’s where we could put the forwarding syntax for
retroactive modelling. Stored properties can’t be defined in extensions, so
if you want to back an implementation with one, you’ll need to make its
conformance explicit in the main body (or we loosen that to at least
extensions in the same file).

// generates thunks to members of this extension in the base type;
// so MyComplexDataType.count —>
MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be
used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re
inside MyComplexDataType
        // No need to pollute internal API with conformance
implementation details.
        // Also, we get errors about non-conformance where we want them —
where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm not sure I understand. What compiler or language support is missing
for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution < >> swift-evolution@swift.org> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution < >>> swift-evolution@swift.org> wrote:

I have been following this discussion (as well as similar threads
earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a
protocol, that means it has all the members specified in the protocol. The
protocol conformance simply codifies a fact about the type itself: namely
that all those members are present.

In this model, any keyword such as `implements` on each conforming
member would introduce substantial boilerplate for negligible gain. The
purpose of a protocol is to communicate that certain members are available,
not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there
is actual implementation being inherited. A conforming type may choose to
roll its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself
define (or redefine!) default implementations for members of that other
protocol. This can create “inheritance chains” of protocol default
implementations. I think there is value in being able to refer to (and
call) the inherited default implementation through some sort of `super`
functionality.

On the other hand, the existence of a default implementation in a
protocol is in large part merely a convenience: a courtesy so that each
conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves
some attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas
put forth, I come down firmly on the side of no keyword for protocol
conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < >>> swift-evolution@swift.org> wrote:

As I mentioned above, I agree that better diagnostics for near-misses
are necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < >>>> swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be
clear
about our intention regarding implementing the requirement, to show
that
this func *depends* on the previous definition of P protocol and to
avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting
point, IMO.
>>>
>>> However, I think it could be improved in one key respect where
previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to
change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some
*other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest
in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will
save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However,
this is
> not the correct error, since S in fact *tries* to conform to P, but
it has
> a mistake in a method signature. This misleads us as to the true
nature of
> the problem, and if S has enough members in it that we fail to spot
the
> existing foo(), we might solve the problem by reimplementing foo(),
and
> leaving the original foo() as dangling dead code. Having an
‘implement’
> keyword on the existing foo() function would change the compiler
error to
> let us know that we have an existing foo() that is incorrectly
declared.
>
> In addition, ‘implement’ can help us when the declaration in
question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword,
because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck
to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite
a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g.
“extension MyClass.MyInternalClass”). It will be easy for autocompletion to
provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own
function called `aFunction()`? What if the same name satisfies 2 protocols,
which do you write?

The way to solve all of the problems in a consistent way is to make the
function actually called “MyProto.aFunction”, and for it to be a separate
function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have
some complex data structure and it has its own API, but I want people to be
able to view it as a Collection. By conforming to Collection, I reserve
lots of keywords and indexing operations which I now can’t use in my own
API. Maybe I’m just providing Collection as a convenience to work with
generic algorithms, but my own API has more efficient semantics for some
operations. We’re relegated to using less-obvious and legible names in
order to avoid conflicts.

We have a way to work around this, which String uses - create a struct
which references your object and calls internal methods such as
“_collection_count” so you can have separate interfaces. This adds up to
quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing
manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and
defines some internal functions to support it.

The String views could then be made in to protocols on String, turning
“UTF8View” in to “UTF8Representable”, and opening up algorithms which can
work on generic sequences of UTF8 bytes. I think that’s pretty cool, and
could open up better integration with other types which are (for example)
UTF8Representable — for example a stream of UTF8 bytes (depending on how
flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as
others here have written. This isn’t like Objective-C where anything that
has the correctly-named methods conforms. Protocol conformances are
completely explicit, and in fact we have empty protocols (“marker
protocols”) for exactly that purpose. I think it is consistent that we make
every member of a conformance specify which protocol it belongs to, and to
have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of
protocols

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

Sorry if that sounds a little bit rude, I’ve been switching between English and German a lot and the way you speak in one language can come across wrong in another!

···

On 21 Sep 2016, at 01:58, Karl <raziel.im+swift-evo@gmail.com> wrote:

I’ve explained it so many times, do you really not understand it?

Basically, protocols are explicit things. They are **not** things that you just “discover” about types at all. We have protocols with no members (“marker protocols”) which are basically used to tag certain types with no other guarantees. That is the important difference between protocols in Swift and in Objective-C. Even if you have implementations for every requirement, if you never explicitly declared conformance you don’t conform. Period.

However, the requirements themselves don’t need to be explicitly marked-up. They just get automatically assigned by the compiler; maybe my property named “count” doesn’t mean the same thing as Collection’s “count”?

I’ve written a lot trying to explain this; please tell me what you don’t understand. To summarise (again):

- Members which satisfy a protocol requirement will have to be explicit about which protocol they belong to
——> They will no longer be automatically assigned as the witness for a protocol requirement

- Members which satisfy a protocol requirement will have the protocol name in their symbolic names (e.g. MyType.someFunction() —> MyType.AProtocol.someFunction())
——> this will allow the same type to conform to protocols with overlapping names, free protocol designers from naming constraints, and reduce the need for “helper structs” to represent alternate views of the same data.
——> Extensions which declare conformance have to satisfy all of their requirements explicitly - by implementing, forwarding to other functions, stored properties or other objects. We can have a shorthand to make this easy.

IMO, we definitely need to solve the overlapping naming problem. If we explicitly assign protocol methods to protocols (as the thread was originally about), this falls out of it.

On 21 Sep 2016, at 01:25, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This was the conversation we were having in the other thread. Perhaps I'm still not understanding something, but I'm not convinced that this feature is an improvement.

Currently, protocols represent a declaration that you have discovered that your type has certain semantics and guarantees a certain API, and you declare that fulfillment "by name only," just as you invoke members "by name only"; unintentional failure to fulfill the contract is a compile-time error. The status quo is precisely my idea of what protocols should be. What are the two ideas you have about them?
On Tue, Sep 20, 2016 at 18:02 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m using String as an example of where this issue of conformance conflicts crops up in the standard library. Ideally, String (or any data type) should be able to conform to protocols whose requirements have conflicting names.
Currently, in order to work around this limitation, you have to delegate the conformance to a supporting type. This is more complicated to write and maintain, and pollutes your internal API. String gives us an example of this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a supporting type instead of directly inside the data-type (String). As an ABI consideration, we should scope all protocol members to their protocols. This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re currently in-between two ideas of what protocols should be - they are explicit but their conformances are resolved by name only and can overlap without warning.

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Sorry, I'm still not sure I understand what you're getting at about this. How would String conforming to Collection multiple times simplify or improve the implementation of String? Or are you arguing it would be better for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.

Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).

// generates thunks to members of this extension in the base type; 
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re inside MyComplexDataType
        // No need to pollute internal API with conformance implementation details.
        // Also, we get errors about non-conformance where we want them — where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I'm not sure I understand. What compiler or language support is missing for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com <mailto:raziel.im+swift-evo@gmail.com>> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

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

I watched this thread with a lot of attention, starting neutral. You must say that Karl won me over. His proposal would make Swift more expressive, and less error prone in cases of protocol conformance with name collisions. I am at this point +1

Jean-Denis

···

Sent from my iPhone

On 22 Sep 2016, at 07:15, Karl via swift-evolution <swift-evolution@swift.org> wrote:

I would like to make it a requirement if not inside a protocol extension which declares a conformance, and actually build the protocol name in to the member in an ABI-breaking way. We could make it additive by generating forwarding thunks from the old symbols to the new ones, but it would be better if we could just solve the overlapping-members problem before then.

That would mean you never get collisions between protocol members. There’s loads of amazing stuff we can do with that ability, and ways we can extend it to reduce a lot of boilerplate that occurs when you want to have multiple representations of the same data (String is just an example).

I don’t really care about the syntax we need to make it liveable. We could automatically insert the protocol names for unambiguous members at call-site, or something else.

This thread was originally about making the *syntax* a requirement; I agree with that, and I would actually take it one (or several) steps further, solving other problems along the way.

On 22 Sep 2016, at 06:46, Russ Bishop <xenadu@gmail.com> wrote:

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
var aVariable : Int
func aFunction()
}
class MyClass : MyProto {
var MyProto.aVariable : Int
func MyProto.aFunction() { … }
}

...

CC-ing Dave A, to understand better if this fits with the vision of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P” should be
to define the entity in an extension that also adds conformance to P.
If that's inadequate indication in some way we should find a way to
enhance it. I wouldn't mind the notation above, but only as a fallback,
not a reuquirement.

--
-Dave
_______________________________________________

Indeed this is exactly how C# handles Interfaces (protocols). The default is the exact same way Swift works - by matching names. If there is a collision you specify Protocol.memberName. Its simple and in the years I was writing C# code it was flexible enough to cover most reasonable scenarios, without adding a bunch of boilerplate.

Russ

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

Hi,

isn't it perfectly fine to conform to multiple unrelated protocols which both require the same member?
Or to declare protocol conformance in some unrelated module?

I would like to make it a requirement if not inside a protocol
extension which declares a conformance, and actually build the
protocol name in to the member in an ABI-breaking way.

IMO, this is much too restrictive.
When we force the protocol name into the member, we make it impossible to conform to multiple protocols.
Well ok, we could create alias names for all protocols.
But often you don't know which protocols to conform to when you compile your module!

What about:

  -- module A --
  class A {
    func foo() {}
  }

  -- module B --
  protocol Foo {
    func foo()
  }
  extension A: Foo {}

What is your ABI name for A.foo()?

Let's keep it simple!
If a simple warning about unrelated methods in a protocol conformance extension solves 95% of our problem,
then we shouldn't overengineer and throw away all our flexibility just to be 100% explicit about which protocol uses which members.

···

Am 2016-09-22 07:15, schrieb Karl via swift-evolution:

--
Martin

I’ve explained it so many times, do you really not understand it?

Basically, protocols are explicit things. They are **not** things that you just “discover” about types at all. We have protocols with no members (“marker protocols”) which are basically used to tag certain types with no other guarantees. That is the important difference between protocols in Swift and in Objective-C. Even if you have implementations for every requirement, if you never explicitly declared conformance you don’t conform. Period.

However, the requirements themselves don’t need to be explicitly marked-up. They just get automatically assigned by the compiler; maybe my property named “count” doesn’t mean the same thing as Collection’s “count”?

I’ve written a lot trying to explain this; please tell me what you don’t understand. To summarise (again):

- Members which satisfy a protocol requirement will have to be explicit about which protocol they belong to
——> They will no longer be automatically assigned as the witness for a protocol requirement

- Members which satisfy a protocol requirement will have the protocol name in their symbolic names (e.g. MyType.someFunction() —> MyType.AProtocol.someFunction())
——> this will allow the same type to conform to protocols with overlapping names, free protocol designers from naming constraints, and reduce the need for “helper structs” to represent alternate views of the same data.

While this solves the problem of overlapping names with different semantics, how would you express the case where the names actually have the same semantics, so that you only want to have one implementor?

protocol A {
  func specficSemantics()
  func sameSemantics()
}

protocol B {
  func specficSemantics()
  func sameSemantics()
}

struct C : A, B {
  // these implementations have to be specific for A and B so Karl’s approach allows to differentiate them
  func A.specficSemantics() { … }
  func B.specficSemantics() { … }

  // this implementation should be shared by A and B because both share the same semantic here
  func sameSemantics() { … } // ??

  // would I have to write it like that (manual delegation to the shared implementation)?
  func sameSemantics() { … }
  func A.sameSemantics() { sameSemantics() }
  func B.sameSemantics() { sameSemantics() }
}

-Thorsten

···

Am 21.09.2016 um 01:58 schrieb Karl via swift-evolution <swift-evolution@swift.org>:

——> Extensions which declare conformance have to satisfy all of their requirements explicitly - by implementing, forwarding to other functions, stored properties or other objects. We can have a shorthand to make this easy.

IMO, we definitely need to solve the overlapping naming problem. If we explicitly assign protocol methods to protocols (as the thread was originally about), this falls out of it.

On 21 Sep 2016, at 01:25, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This was the conversation we were having in the other thread. Perhaps I'm still not understanding something, but I'm not convinced that this feature is an improvement.

Currently, protocols represent a declaration that you have discovered that your type has certain semantics and guarantees a certain API, and you declare that fulfillment "by name only," just as you invoke members "by name only"; unintentional failure to fulfill the contract is a compile-time error. The status quo is precisely my idea of what protocols should be. What are the two ideas you have about them?
On Tue, Sep 20, 2016 at 18:02 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m using String as an example of where this issue of conformance conflicts crops up in the standard library. Ideally, String (or any data type) should be able to conform to protocols whose requirements have conflicting names.
Currently, in order to work around this limitation, you have to delegate the conformance to a supporting type. This is more complicated to write and maintain, and pollutes your internal API. String gives us an example of this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a supporting type instead of directly inside the data-type (String). As an ABI consideration, we should scope all protocol members to their protocols. This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re currently in-between two ideas of what protocols should be - they are explicit but their conformances are resolved by name only and can overlap without warning.

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Sorry, I'm still not sure I understand what you're getting at about this. How would String conforming to Collection multiple times simplify or improve the implementation of String? Or are you arguing it would be better for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com <mailto:razielim@gmail.com>> wrote:
I’m not saying vital support is missing, just that it is more awkward. String doesn’t conform to collection, String.UTF8View does; so if you change some implementation detail (in StringCore, because that’s where they live for String), you get the error popping up somewhere other than the place you just changed. That’s what I mean when I say “language support”. If you do what StringCore does, and you’re changing stuff which is ultimately going to be used to conform to, say, Collection, you have to build distance between the implementation and the (only) conformance it is used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements “InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave inside the type, otherwise we’d need to expose a bunch of implementation details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to Collection multiple times with different indexes and results). It’s a lot of work to maintain, especially if you have evolving protocols that are conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same time, since we’re now being explicit about which protocol requirement is satisfied where - we should also be able to delegate our conformance, telling the compiler to dispatch any unimplemented methods to another object. For example, lets say you want to wrap a Collection and observe mutations to it; you might override replaceSubrange(), but every other method (such as count, index(after:)… all the rest) is just a forwarding function.

Interestingly, we could do this safely (from a code legibility perspective) if we say that every scope which adds a conformance must completely satisfy its requirements, which we would more reasonably be able to require if we made this change (so your internal functions can still be wherever you like, but they won’t automatically satisfy a protocol requirement if they happen to have the same name). Then we could reasonably say that if you add an extension which adds a conformance to, say, Collection, you have to tell us where to find every one of its requirements. That’s where we could put the forwarding syntax for retroactive modelling. Stored properties can’t be defined in extensions, so if you want to back an implementation with one, you’ll need to make its conformance explicit in the main body (or we loosen that to at least extensions in the same file).

// generates thunks to members of this extension in the base type; 
// so MyComplexDataType.count —> MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re inside MyComplexDataType
        // No need to pollute internal API with conformance implementation details.
        // Also, we get errors about non-conformance where we want them — where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

I'm not sure I understand. What compiler or language support is missing for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com <mailto:raziel.im+swift-evo@gmail.com>> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.

In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.

On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.

A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be clear
about our intention regarding implementing the requirement, to show that
this func *depends* on the previous definition of P protocol and to avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org> <mailto:swift-evolution@swift.org <mailto:swift-evolution@swift.org>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.
>>>
>>> However, I think it could be improved in one key respect where previous
>>> proposals using `override` are superior. Namely, the proposed `implement`
>>> keyword adds no additional safety when a type implements a protocol
>>> requirement that doesn't have a default implementation. This is because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some *other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However, this is
> not the correct error, since S in fact *tries* to conform to P, but it has
> a mistake in a method signature. This misleads us as to the true nature of
> the problem, and if S has enough members in it that we fail to spot the
> existing foo(), we might solve the problem by reimplementing foo(), and
> leaving the original foo() as dangling dead code. Having an ‘implement’
> keyword on the existing foo() function would change the compiler error to
> let us know that we have an existing foo() that is incorrectly declared.
>
> In addition, ‘implement’ can help us when the declaration in question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword, because
> foo() does not have a signature matching anything in the protocol, whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol, e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?

The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.

We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and defines some internal functions to support it.

The String views could then be made in to protocols on String, turning “UTF8View” in to “UTF8Representable”, and opening up algorithms which can work on generic sequences of UTF8 bytes. I think that’s pretty cool, and could open up better integration with other types which are (for example) UTF8Representable — for example a stream of UTF8 bytes (depending on how flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of protocols

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

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

No problem! I understand *what* your proposal is. I don't understand what
benefit it has over the status quo.

Currently, when you say that your type T conforms to Collection, you are
not only guaranteeing that T has a member named count, you are also making
the guarantee that T.count meets the semantic requirements of
Collection.count. That is why protocol conformance is explicit. If count is
a member of T but does not meet the semantic guarantees of
Collection.count, then you should not conform T to Collection. So yes, a
protocol conformance *is* a fact you discover about a type.

I'm not yet convinced we "need" to solve the overlapping problem, as still
no one has demonstrated a real-world use case. If there is one, I think
there are far more surgical and additive approaches. But that is not the
topic of this thread.

···

On Tue, Sep 20, 2016 at 7:01 PM Karl <razielim@gmail.com> wrote:

Sorry if that sounds a little bit rude, I’ve been switching between
English and German a lot and the way you speak in one language can come
across wrong in another!

On 21 Sep 2016, at 01:58, Karl <raziel.im+swift-evo@gmail.com> wrote:

I’ve explained it so many times, do you really not understand it?

Basically, protocols are explicit things. They are **not** things that you
just “discover” about types at all. We have protocols with no members
(“marker protocols”) which are basically used to tag certain types with no
other guarantees. That is the important difference between protocols in
Swift and in Objective-C. Even if you have implementations for every
requirement, if you never explicitly declared conformance you don’t
conform. Period.

However, the requirements themselves don’t need to be explicitly
marked-up. They just get automatically assigned by the compiler; maybe my
property named “count” doesn’t mean the same thing as Collection’s “count”?

I’ve written a lot trying to explain this; please tell me what you don’t
understand. To summarise (again):

- Members which satisfy a protocol requirement will have to be explicit
about which protocol they belong to
——> They will no longer be automatically assigned as the witness for a
protocol requirement

- Members which satisfy a protocol requirement will have the protocol name
in their symbolic names (e.g. MyType.someFunction() —>
MyType.AProtocol.someFunction())
——> this will allow the same type to conform to protocols with overlapping
names, free protocol designers from naming constraints, and reduce the need
for “helper structs” to represent alternate views of the same data.
——> Extensions which declare conformance have to satisfy all of their
requirements explicitly - by implementing, forwarding to other functions,
stored properties or other objects. We can have a shorthand to make this
easy.

IMO, we definitely need to solve the overlapping naming problem. If we
explicitly assign protocol methods to protocols (as the thread was
originally about), this falls out of it.

On 21 Sep 2016, at 01:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This was the conversation we were having in the other thread. Perhaps I'm
still not understanding something, but I'm not convinced that this feature
is an improvement.

Currently, protocols represent a declaration that you have discovered that
your type has certain semantics and guarantees a certain API, and you
declare that fulfillment "by name only," just as you invoke members "by
name only"; unintentional failure to fulfill the contract is a compile-time
error. The status quo is precisely my idea of what protocols should be.
What are the two ideas you have about them?
On Tue, Sep 20, 2016 at 18:02 Karl <razielim@gmail.com> wrote:

I’m using String as an example of where this issue of conformance
conflicts crops up in the standard library. Ideally, String (or any data
type) should be able to conform to protocols whose requirements have
conflicting names.
Currently, in order to work around this limitation, you have to delegate
the conformance to a supporting type. This is more complicated to write and
maintain, and pollutes your internal API. String gives us an example of
this, but it’s not the worst example.
It basically implements what I’m talking about anyway, but manually via a
supporting type instead of directly inside the data-type (String). As an
ABI consideration, we should scope all protocol members to their protocols.
This would resolve all naming conflicts.

I can’t understand how anybody would argue for the status quo - we’re
currently in-between two ideas of what protocols should be - they are
explicit but their conformances are resolved by name only and can overlap
without warning.

On 21 Sep 2016, at 00:48, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Sorry, I'm still not sure I understand what you're getting at about this.
How would String conforming to Collection multiple times simplify or
improve the implementation of String? Or are you arguing it would be better
for users of String? If so, how?

On Tue, Sep 20, 2016 at 17:26 Karl <razielim@gmail.com> wrote:

I’m not saying vital support is missing, just that it is more awkward.
String doesn’t conform to collection, String.UTF8View does; so if you
change some implementation detail (in StringCore, because that’s where they
live for String), you get the error popping up somewhere other than the
place you just changed. That’s what I mean when I say “language support”.
If you do what StringCore does, and you’re changing stuff which is
ultimately going to be used to conform to, say, Collection, you have to
build distance between the implementation and the (only) conformance it is
used for, and it’s less optimal.

Let’s say I have an object MyComplexDataType, it implements
“InternalStructureView” and “Collection”:

protocol InternalStructureView {
    associatedtype Index
    var count : Int { get } // whatever, just some stuff that will cause
a name conflict
    func doInternalMagic(at: Index)
}

struct MyComplexDataType {
    var __collection_count : Int {
        // This is quite a complex operation which we’d rather leave
inside the type, otherwise we’d need to expose a bunch of implementation
details internally
    }
   var __internal_count : Int {
       // Again, best left here
   }

   struct CollectionView  : Collection {
       init(parent: MyComplexDataType) { … }
        var count { return parent.__collection_count }
        // ...etc
   }

  struct InternalStructure : InternalStructureView {
      init(parent: MyComplexDataType) { … }
      var count { return parent.__internal_count }
      // ...etc
  }

  var collection : CollectionView { return CollectionView(self) }
  var internalStructure : InternalStructure { return
InternalStructure(self) }
}

This is basically what String does (except that it wants to conform to
Collection multiple times with different indexes and results). It’s a lot
of work to maintain, especially if you have evolving protocols that are
conformed to in several places.
We should have a better solution. We should be able to define:

“protocol UTF8Collection : Collection {}
protocol UTF16Collection : Collection {}”

and have String conform to both of them at the same time. At the same
time, since we’re now being explicit about which protocol requirement is
satisfied where - we should also be able to delegate our conformance,
telling the compiler to dispatch any unimplemented methods to another
object. For example, lets say you want to wrap a Collection and observe
mutations to it; you might override replaceSubrange(), but every other
method (such as count, index(after:)… all the rest) is just a forwarding
function.

Interestingly, we could do this safely (from a code legibility
perspective) if we say that every scope which adds a conformance must
completely satisfy its requirements, which we would more reasonably be able
to require if we made this change (so your internal functions can still be
wherever you like, but they won’t automatically satisfy a protocol
requirement if they happen to have the same name). Then we could reasonably
say that if you add an extension which adds a conformance to, say,
Collection, you have to tell us where to find every one of its
requirements. That’s where we could put the forwarding syntax for
retroactive modelling. Stored properties can’t be defined in extensions, so
if you want to back an implementation with one, you’ll need to make its
conformance explicit in the main body (or we loosen that to at least
extensions in the same file).

// generates thunks to members of this extension in the base type;
// so MyComplexDataType.count —>
MyComplexDataType.InternalStructure.count,
// to account for conformance being added in later version. Can also be
used for renamed protocols, and be tagged on individual members.

@makeAvailable(as: _)
extension MyComplexDataType : InternalStructure {

   typealias Index = InternalIndexType
    var count : Int {
        // We have access to all of the private members because we’re
inside MyComplexDataType
        // No need to pollute internal API with conformance
implementation details.
        // Also, we get errors about non-conformance where we want them
— where the implementation is.
    }
    func doInternalMagic(at: Index) {
       ...
    }
}

On 20 Sep 2016, at 23:46, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm not sure I understand. What compiler or language support is missing
for StringCore?
On Tue, Sep 20, 2016 at 16:42 Karl via swift-evolution < >>> swift-evolution@swift.org> wrote:

On 20 Sep 2016, at 23:28, Karl <raziel.im+swift-evo@gmail.com> wrote:

On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution < >>>> swift-evolution@swift.org> wrote:

I have been following this discussion (as well as similar threads
earlier this year) and listening to the ideas put forth by all sides.

It seems to me that the fundamental difference between classes and
protocols is that classes inherit implementation whereas protocol
conformance is a promise about interface.

When a class or struct or enum declares itself as conforming to a
protocol, that means it has all the members specified in the protocol. The
protocol conformance simply codifies a fact about the type itself: namely
that all those members are present.

In this model, any keyword such as `implements` on each conforming
member would introduce substantial boilerplate for negligible gain. The
purpose of a protocol is to communicate that certain members are available,
not to make declaring those members more onerous.

However, default implementations for protocols blur the line. Now there
is actual implementation being inherited. A conforming type may choose to
roll its own version of a method, or to utilize the default provided by the
protocol. This is closer to the situation with subclassing.

Moreover, a protocol which conforms to another protocol may itself
define (or redefine!) default implementations for members of that other
protocol. This can create “inheritance chains” of protocol default
implementations. I think there is value in being able to refer to (and
call) the inherited default implementation through some sort of `super`
functionality.

On the other hand, the existence of a default implementation in a
protocol is in large part merely a convenience: a courtesy so that each
conforming type need not rewrite the same boilerplate code.

A type which conforms to a protocol may accept the default or it may
provide its own implementation, but it is not “overriding” anything. The
default implementation was offered as a convenience, to be taken or left as
needed. Thus I do not think any keyword (neither `override` nor
`implements`) should be required in that case either.

The frequently-raised point regarding near-miss member names deserves
some attention. Several people have expressed a desire for the compiler to
assist them in determining whether a given member does or does not meet a
protocol requirement. Specifically, when a type conforms to a protocol with
a default implementation, and the type defines a member with a similar
signature, it is not obvious at glance if that member matches the protocol.

I think this is a job for linters and IDEs. For example, syntax
highlighting could distinguish members which satisfy a protocol
requirement, thereby providing immediate visual confirmation of success.

Having followed the lengthy discussion and weighed the numerous ideas
put forth, I come down firmly on the side of no keyword for protocol
conformance.

A protocol describes an interface and provides a set of customization
points. It may also, as a convenience, offer default implementations. The
protocol simply describes the capabilities of its conforming types, and any
default implementations are there to make things easier for them.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin

On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution < >>>> swift-evolution@swift.org> wrote:

As I mentioned above, I agree that better diagnostics for near-misses
are necessary, but they are possible without new syntax. There is no win in
avoiding unintentional behavior because, without a default implementation,
these issues are caught at compile time already.

On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

> extension P {
> implement func foo() -> [String : String] { return [:] }
> }

Yes, it seems like we need `implement` (or `override` as another
suggestion) in protocol extension also just for the same reasons - be
clear
about our intention regarding implementing the requirement, to show
that
this func *depends* on the previous definition of P protocol and to
avoid
possible mistakes related to protocol conformance.

On 20.09.2016 17:38, Charles Srstka wrote:
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution >>>>>> >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> >>>>>> wrote:
>>
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
>>> I definitely think Vladimir's suggestion is a great starting
point, IMO.
>>>
>>> However, I think it could be improved in one key respect where
previous
>>> proposals using `override` are superior. Namely, the proposed
`implement`
>>> keyword adds no additional safety when a type implements a
protocol
>>> requirement that doesn't have a default implementation. This is
because, if
>>
>> Yes, *at the moment of writing* the type's code there could be no
default
>> implementation for protocol requirement. But, *at the moment of
>> compilation* such default implementation could appear.
>>
>> Let's discuss such scenario in case we'll take your suggestion:
>>
>> You got SomeClass.swift file, 3rd party file you don't want to
change or
>> changes are not allowed. Content:
>>
>> public protocol SomeProtocol {
>> func foo()
>> }
>>
>> public class SomeClass : SomeProtocol {
>> func foo() {...} // no default implementation *at the moment of
writing*,
>> no need in `overload`
>> }
>>
>> Now, you adds SomeClass.swift file to your project and in some
*other*
>> file you write:
>>
>> extension SomeProtocol {
>> func foo() {...}
>> }
>>
>> As you see, you don't control the SomeClass.swift but you suggest
in this
>> case SomeClass.foo() should be defined with `override`.
>>
>> With 'implement' SomeClass.foo() will be marked initially and will
save
>> us if protocol's requirement PLUS default implementation changed.
>
> Requiring the ‘implement’ keyword can help us even if no default
> implementation is involved. Consider:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> struct S : P {
> func foo() -> [String : String] { return [:] }
> }
>
> We will get an error here that S does not conform to P. However,
this is
> not the correct error, since S in fact *tries* to conform to P, but
it has
> a mistake in a method signature. This misleads us as to the true
nature of
> the problem, and if S has enough members in it that we fail to spot
the
> existing foo(), we might solve the problem by reimplementing foo(),
and
> leaving the original foo() as dangling dead code. Having an
‘implement’
> keyword on the existing foo() function would change the compiler
error to
> let us know that we have an existing foo() that is incorrectly
declared.
>
> In addition, ‘implement’ can help us when the declaration in
question *is*
> the default implementation:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> implement func foo() -> [String : String] { return [:] }
> }
>
> Here we will get an error with the proposed ‘implement’ keyword,
because
> foo() does not have a signature matching anything in the protocol,
whereas
> without ‘implement’ we would happily and silently generate a useless
> dangling function that would never be used, and then pass the buck
to the
> concrete type that implements P:
>
> protocol P {
> func foo() -> [String : Any]
> }
>
> extension P {
> func foo() -> [String : String] { return [:] } // The error is here:
> }
>
> struct S : P {} // But it gets reported here.
>
> Charles
>
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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

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

I agree that a new keyword is unwanted. Conforming to protocols is
quite a common thing, so you want it to be easy to remember.

I think the best way is to prefix the member name with the protocol,
e.g:

protocol MyProto {
    var aVariable : Int
    func aFunction()
}
class MyClass : MyProto {
    var MyProto.aVariable : Int
    func MyProto.aFunction() { … }
}

This is consistent with how we refer to other members of types (e.g.
“extension MyClass.MyInternalClass”). It will be easy for autocompletion to
provide good suggestions, too.
As I see it, the only problem is what if `MyClass` wants its own
function called `aFunction()`? What if the same name satisfies 2 protocols,
which do you write?

The way to solve all of the problems in a consistent way is to make the
function actually called “MyProto.aFunction”, and for it to be a separate
function from plain “aFunction()” or from “SomeotherProto.aFunction”.

I believe it is crucial to protocols that we can do this. Maybe I have
some complex data structure and it has its own API, but I want people to be
able to view it as a Collection. By conforming to Collection, I reserve
lots of keywords and indexing operations which I now can’t use in my own
API. Maybe I’m just providing Collection as a convenience to work with
generic algorithms, but my own API has more efficient semantics for some
operations. We’re relegated to using less-obvious and legible names in
order to avoid conflicts.

We have a way to work around this, which String uses - create a struct
which references your object and calls internal methods such as
“_collection_count” so you can have separate interfaces. This adds up to
quite a lot of boilerplate and maintenance overhead.

Also to add here: you’re basically implementing what I’m proposing
manually if you do this; only you don’t get language/compiler support.
String basically does this - it shares StringCore with UTF8View and
defines some internal functions to support it.

The String views could then be made in to protocols on String, turning
“UTF8View” in to “UTF8Representable”, and opening up algorithms which can
work on generic sequences of UTF8 bytes. I think that’s pretty cool, and
could open up better integration with other types which are (for example)
UTF8Representable — for example a stream of UTF8 bytes (depending on how
flexible implementation allows us to make the protocol).

I don’t agree that Protocol conformances are kind-of incidental, as
others here have written. This isn’t like Objective-C where anything that
has the correctly-named methods conforms. Protocol conformances are
completely explicit, and in fact we have empty protocols (“marker
protocols”) for exactly that purpose. I think it is consistent that we make
every member of a conformance specify which protocol it belongs to, and to
have its name scoped to that protocol.

Karl

CC-ing Dave A, to understand better if this fits with the vision of
protocols

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

Hi,

isn't it perfectly fine to conform to multiple unrelated protocols
which both require the same member?

Yeah, but in practice it *basically* never happens, to the point where
I'd be fine requiring boilerplate repetition if you wanted to satisfy
requirements of two protocols unrelated by refinement with the same
declaration.

···

on Thu Sep 22 2016, Martin Waitz <tali-AT-admingilde.org> wrote:

Or to declare protocol conformance in some unrelated module?

Am 2016-09-22 07:15, schrieb Karl via swift-evolution:

I would like to make it a requirement if not inside a protocol
extension which declares a conformance, and actually build the
protocol name in to the member in an ABI-breaking way.

IMO, this is much too restrictive.
When we force the protocol name into the member, we make it impossible
to conform to multiple protocols.
Well ok, we could create alias names for all protocols.
But often you don't know which protocols to conform to when you
compile your module!

What about:

-- module A --
class A {
   func foo() {}
}

-- module B --
protocol Foo {
   func foo()
}
extension A: Foo {}

What is your ABI name for A.foo()?

Let's keep it simple!
If a simple warning about unrelated methods in a protocol conformance
extension solves 95% of our problem,
then we shouldn't overengineer and throw away all our flexibility just
to be 100% explicit about which protocol uses which members.

--
-Dave

I watched this thread with a lot of attention, starting neutral. You
must say that Karl won me over. His proposal would make Swift more
expressive, and less error prone in cases of protocol conformance with
name collisions. I am at this point +1

Actually I also support Karl's suggestion in general. It is trying to solve IMO important problems and make Swift's protocol programming safer and less fragile. Also it adds new interested features for working with protocols.

But in reality, I don't feel like his suggestion could be accepted by core team and community and even if it could be supported, it seems for me that *implementation* of his proposal requires a huge amount of time and big changes in how Swift is working currently. (Probably some one who knows Swift internals could comment regarding this)
So, theoretically we'd have these improvements not in near future and I think the problem discussed is very important to be addressed in Swift as soon as possible.
I base my opinion also on previous discussions regarding similar subjects.

My suggestion regarding a marker for protocol implementation method/prop in type - solves most of the addressed problems with protocol conformance and with fragile of such conformance, and adds one new keyword (or even zero - right now I think the `override` is better choice for such "marker"). I believe this proposal could be implemented with much less amount of work and with less changes to current internals of Swift and to current code base, and so we can have such a big improvement in Swift soon. So my intention was to suggest solution that can dramatically improve Swift's protocol programming with "small" amount of changes for compiler(internals) and for existed sources.

But it seems like the direction chosen by the core team and supported by many in community - is just a warning if extension conforming type to protocol contains unrelated to that protocol methods/props. I see that this solution can improve protocol programming in some areas, but does not address some IMO important issues we discussed in the thread :

* Currently extension can not have stored properties. So, if we want to implement protocol's props as stored properties - we can't move them to extension. So to implement this soulution - we need stored properties in extensions. It is not clear if and when they are expected.

* This solution will not require the safety(regarding protocol conformance) from a developer, it will only inform and only if protocol conformance defined in extension. So, when you use 3rd party source code - your project will not be protected for the discussed problems.

* To write safe code I can't group methods/props as I want, I have to declare a number of extensions per-protocol (in case my type conforms to a number of protocols)

* This solution does not solve problem of near-miss signature of method definition in protocol extension like here:
protocol A { func foo() }
protocol B : A {}
extension A { func foo() }
extension B { func voo() } // typo. how to "mark" this should be impl?
"my" suggestion:
extension A { override func foo() }
extension B { override func foo() }

* Not clear how to write safe code with that approach if we implement protocol requirement in derived class, but conformance was declared in base (but not implemented) :
protocol P { func foo() }
extension P { func foo() }
class A : P {}
class B { func foo() } // we can't move this to extension, B already conforms to P
, and in opposite to "my" `override` requirement for implementation, if `A` will add its own foo() implementation - we'll have to change B's definition(need to add `override` for B.foo )
"my" suggestion:
class B { override func foo() }

···

On 22.09.2016 11:10, Jean-Denis Muys via swift-evolution wrote:

Jean-Denis

Sent from my iPhone

On 22 Sep 2016, at 07:15, Karl via swift-evolution >> <swift-evolution@swift.org> wrote:

I would like to make it a requirement if not inside a protocol
extension which declares a conformance, and actually build the
protocol name in to the member in an ABI-breaking way. We could make
it additive by generating forwarding thunks from the old symbols to
the new ones, but it would be better if we could just solve the
overlapping-members problem before then.

That would mean you never get collisions between protocol members.
There’s loads of amazing stuff we can do with that ability, and ways
we can extend it to reduce a lot of boilerplate that occurs when you
want to have multiple representations of the same data (String is just
an example).

I don’t really care about the syntax we need to make it liveable. We
could automatically insert the protocol names for unambiguous members
at call-site, or something else.

This thread was originally about making the *syntax* a requirement; I
agree with that, and I would actually take it one (or several) steps
further, solving other problems along the way.

On 22 Sep 2016, at 06:46, Russ Bishop <xenadu@gmail.com> wrote:

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution >>>> <swift-evolution@swift.org> wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

I think the best way is to prefix the member name with the
protocol, e.g:

protocol MyProto { var aVariable : Int func aFunction() } class
MyClass : MyProto { var MyProto.aVariable : Int func
MyProto.aFunction() { … } }

...

CC-ing Dave A, to understand better if this fits with the vision
of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P”
should be to define the entity in an extension that also adds
conformance to P. If that's inadequate indication in some way we
should find a way to enhance it. I wouldn't mind the notation
above, but only as a fallback, not a reuquirement.

-- -Dave _______________________________________________

Indeed this is exactly how C# handles Interfaces (protocols). The
default is the exact same way Swift works - by matching names. If
there is a collision you specify Protocol.memberName. Its simple and
in the years I was writing C# code it was flexible enough to cover
most reasonable scenarios, without adding a bunch of boilerplate.

Russ

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

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

That does not seem right to me. A does not implement any protocol.
The extension of A implements a protocol thus foo() should not be seen as part of the protocol at all.

So far, I have always extended a class when adding protocol compliance. I.e. it is always clear

I.e.

protocol P {
func foo()
}

class A {
fun foo() {} // Should not be regarded as implementation of P
}

extension A: P {
func foo() {} // This is the implementation of P
}

···

On 22 Sep 2016, at 11:28, Martin Waitz via swift-evolution <swift-evolution@swift.org> wrote:

Hi,

isn't it perfectly fine to conform to multiple unrelated protocols which both require the same member?
Or to declare protocol conformance in some unrelated module?

Am 2016-09-22 07:15, schrieb Karl via swift-evolution:

I would like to make it a requirement if not inside a protocol
extension which declares a conformance, and actually build the
protocol name in to the member in an ABI-breaking way.

IMO, this is much too restrictive.
When we force the protocol name into the member, we make it impossible to conform to multiple protocols.
Well ok, we could create alias names for all protocols.
But often you don't know which protocols to conform to when you compile your module!

What about:

-- module A --
class A {
  func foo() {}
}

-- module B --
protocol Foo {
  func foo()
}
extension A: Foo {}

What is your ABI name for A.foo()?

Let's keep it simple!
If a simple warning about unrelated methods in a protocol conformance extension solves 95% of our problem,
then we shouldn't overengineer and throw away all our flexibility just to be 100% explicit about which protocol uses which members.

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

The cases where you find these kinds of exact collisions are so rare (never in my
career) that it's fine if some manual work is needed.

···

on Tue Sep 27 2016, Thorsten Seitz <tseitz42-AT-icloud.com> wrote:

While this solves the problem of overlapping names with different
semantics, how would you express the case where the names actually
have the same semantics, so that you only want to have one
implementor?

protocol A {
  func specficSemantics()
  func sameSemantics()
}

protocol B {
  func specficSemantics()
  func sameSemantics()
}

struct C : A, B {
  // these implementations have to be specific for A and B so Karl’s approach allows to differentiate them
  func A.specficSemantics() { … }
  func B.specficSemantics() { … }

  // this implementation should be shared by A and B because both share the same semantic here
  func sameSemantics() { … } // ??

  // would I have to write it like that (manual delegation to the shared implementation)?
  func sameSemantics() { … }
  func A.sameSemantics() { sameSemantics() }
  func B.sameSemantics() { sameSemantics() }
}

-Thorsten

--
-Dave

Extensions in Swift aren't a first-class entity; they have no name and no
representation in the type system. If an extension to A does something,
then A does something. If A conforms to P, then A.foo is the implementation
of P.foo.

···

On Thu, Sep 22, 2016 at 11:06 Marinus van der Lugt via swift-evolution < swift-evolution@swift.org> wrote:

That does not seem right to me. A does not implement any protocol.
The extension of A implements a protocol thus foo() should not be seen as
part of the protocol at all.

So far, I have always extended a class when adding protocol compliance.
I.e. it is always clear

I.e.

protocol P {
func foo()
}

class A {
fun foo() {} // Should not be regarded as implementation of P
}

extension A: P {
func foo() {} // This is the implementation of P
}

>
> On 22 Sep 2016, at 11:28, Martin Waitz via swift-evolution < > swift-evolution@swift.org> wrote:
>
> Hi,
>
> isn't it perfectly fine to conform to multiple unrelated protocols which
both require the same member?
> Or to declare protocol conformance in some unrelated module?
>
> Am 2016-09-22 07:15, schrieb Karl via swift-evolution:
>> I would like to make it a requirement if not inside a protocol
>> extension which declares a conformance, and actually build the
>> protocol name in to the member in an ABI-breaking way.
>
> IMO, this is much too restrictive.
> When we force the protocol name into the member, we make it impossible
to conform to multiple protocols.
> Well ok, we could create alias names for all protocols.
> But often you don't know which protocols to conform to when you compile
your module!
>
> What about:
>
> -- module A --
> class A {
> func foo() {}
> }
>
> -- module B --
> protocol Foo {
> func foo()
> }
> extension A: Foo {}
>
> What is your ABI name for A.foo()?
>
> Let's keep it simple!
> If a simple warning about unrelated methods in a protocol conformance
extension solves 95% of our problem,
> then we shouldn't overengineer and throw away all our flexibility just
to be 100% explicit about which protocol uses which members.
>
> --
> Martin
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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

I'd also say that one or two keywords are superior than the protocol naming approach in terms of implementation simplicity (for the core team).

My suggestions:

Either "conform" or "implement" should be a required keyword for all properties/functions which implement a protocol (also in protocol extensions)

"override" should be used if a default implementation or a member of a superclass is overridden.

If you are overriding a default implementation of a protocol "conform" / "implement" is also required.

// Retroactive conformance (old behavior) but only in extensions
extension Foo: @retroactive Baz {
    // only some members of Baz are implemented here (they need the keywords)
    // the other members outside the extension don't need any additional keywords
    // note: you can use "@retroactive" and "conform" in conjunction
}

Future directions:
"conform(ProtocolName)" / "override(ProtocolName)" can be used to disambiguate.

// reducing boilerplate
extension Foo: conform Bar {
    // These declarations can only implement Bar and don't need the "conform" keyword
}

Final question:
Should we also require a marker for implemented protocol members in the interface?:

protocol Foo {
    defaulted func foo()
}
extension Foo {
    implement func foo()
}

Best regards
Maximilian

···

Am 22.09.2016 um 16:44 schrieb Vladimir.S via swift-evolution <swift-evolution@swift.org>:

On 22.09.2016 11:10, Jean-Denis Muys via swift-evolution wrote:
I watched this thread with a lot of attention, starting neutral. You
must say that Karl won me over. His proposal would make Swift more
expressive, and less error prone in cases of protocol conformance with
name collisions. I am at this point +1

Actually I also support Karl's suggestion in general. It is trying to solve IMO important problems and make Swift's protocol programming safer and less fragile. Also it adds new interested features for working with protocols.

But in reality, I don't feel like his suggestion could be accepted by core team and community and even if it could be supported, it seems for me that *implementation* of his proposal requires a huge amount of time and big changes in how Swift is working currently. (Probably some one who knows Swift internals could comment regarding this)
So, theoretically we'd have these improvements not in near future and I think the problem discussed is very important to be addressed in Swift as soon as possible.
I base my opinion also on previous discussions regarding similar subjects.

My suggestion regarding a marker for protocol implementation method/prop in type - solves most of the addressed problems with protocol conformance and with fragile of such conformance, and adds one new keyword (or even zero - right now I think the `override` is better choice for such "marker"). I believe this proposal could be implemented with much less amount of work and with less changes to current internals of Swift and to current code base, and so we can have such a big improvement in Swift soon. So my intention was to suggest solution that can dramatically improve Swift's protocol programming with "small" amount of changes for compiler(internals) and for existed sources.

But it seems like the direction chosen by the core team and supported by many in community - is just a warning if extension conforming type to protocol contains unrelated to that protocol methods/props. I see that this solution can improve protocol programming in some areas, but does not address some IMO important issues we discussed in the thread :

* Currently extension can not have stored properties. So, if we want to implement protocol's props as stored properties - we can't move them to extension. So to implement this soulution - we need stored properties in extensions. It is not clear if and when they are expected.

* This solution will not require the safety(regarding protocol conformance) from a developer, it will only inform and only if protocol conformance defined in extension. So, when you use 3rd party source code - your project will not be protected for the discussed problems.

* To write safe code I can't group methods/props as I want, I have to declare a number of extensions per-protocol (in case my type conforms to a number of protocols)

* This solution does not solve problem of near-miss signature of method definition in protocol extension like here:
protocol A { func foo() }
protocol B : A {}
extension A { func foo() }
extension B { func voo() } // typo. how to "mark" this should be impl?
"my" suggestion:
extension A { override func foo() }
extension B { override func foo() }

* Not clear how to write safe code with that approach if we implement protocol requirement in derived class, but conformance was declared in base (but not implemented) :
protocol P { func foo() }
extension P { func foo() }
class A : P {}
class B { func foo() } // we can't move this to extension, B already conforms to P
, and in opposite to "my" `override` requirement for implementation, if `A` will add its own foo() implementation - we'll have to change B's definition(need to add `override` for B.foo )
"my" suggestion:
class B { override func foo() }

Jean-Denis

Sent from my iPhone

On 22 Sep 2016, at 07:15, Karl via swift-evolution >>> <swift-evolution@swift.org> wrote:

I would like to make it a requirement if not inside a protocol
extension which declares a conformance, and actually build the
protocol name in to the member in an ABI-breaking way. We could make
it additive by generating forwarding thunks from the old symbols to
the new ones, but it would be better if we could just solve the
overlapping-members problem before then.

That would mean you never get collisions between protocol members.
There’s loads of amazing stuff we can do with that ability, and ways
we can extend it to reduce a lot of boilerplate that occurs when you
want to have multiple representations of the same data (String is just
an example).

I don’t really care about the syntax we need to make it liveable. We
could automatically insert the protocol names for unambiguous members
at call-site, or something else.

This thread was originally about making the *syntax* a requirement; I
agree with that, and I would actually take it one (or several) steps
further, solving other problems along the way.

On 22 Sep 2016, at 06:46, Russ Bishop <xenadu@gmail.com> wrote:

On Sep 20, 2016, at 4:34 PM, Dave Abrahams via swift-evolution >>>>> <swift-evolution@swift.org> wrote:

on Tue Sep 20 2016, Karl <razielim-AT-gmail.com> wrote:

I think the best way is to prefix the member name with the
protocol, e.g:

protocol MyProto { var aVariable : Int func aFunction() } class
MyClass : MyProto { var MyProto.aVariable : Int func
MyProto.aFunction() { … } }

...

CC-ing Dave A, to understand better if this fits with the vision
of protocols

I generally agree with Doug. The canonical way to indicate “this
method/property/type implements a requirement of protocol P”
should be to define the entity in an extension that also adds
conformance to P. If that's inadequate indication in some way we
should find a way to enhance it. I wouldn't mind the notation
above, but only as a fallback, not a reuquirement.

-- -Dave _______________________________________________

Indeed this is exactly how C# handles Interfaces (protocols). The
default is the exact same way Swift works - by matching names. If
there is a collision you specify Protocol.memberName. Its simple and
in the years I was writing C# code it was flexible enough to cover
most reasonable scenarios, without adding a bunch of boilerplate.

Russ

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

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

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

I agree with that. I believe I have more often run into name collisions for
protocols with differing semantics then matching semantics. Actually far
more often then both I have purposely used somewhat contrived naming in
protocols to avoid collisions, if that can be avoided by leveraging the
implicit namespacing that exists in the protocol's name; it would be nice
language feature IMHO.

···

On Tue, Sep 27, 2016 at 7:51 AM Dave Abrahams via swift-evolution < swift-evolution@swift.org> wrote:

on Tue Sep 27 2016, Thorsten Seitz <tseitz42-AT-icloud.com> wrote:

> While this solves the problem of overlapping names with different
> semantics, how would you express the case where the names actually
> have the same semantics, so that you only want to have one
> implementor?
>
> protocol A {
> func specficSemantics()
> func sameSemantics()
> }
>
> protocol B {
> func specficSemantics()
> func sameSemantics()
> }
>
> struct C : A, B {
> // these implementations have to be specific for A and B so Karl’s
approach allows to differentiate them
> func A.specficSemantics() { … }
> func B.specficSemantics() { … }
>
> // this implementation should be shared by A and B because both
share the same semantic here
> func sameSemantics() { … } // ??
>
> // would I have to write it like that (manual delegation to the
shared implementation)?
> func sameSemantics() { … }
> func A.sameSemantics() { sameSemantics() }
> func B.sameSemantics() { sameSemantics() }
> }
>
> -Thorsten

The cases where you find these kinds of exact collisions are so rare
(never in my
career) that it's fine if some manual work is needed.

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