[swift-evolution] Proposal: Split extensions into implementing methods and adding static functions Was: [swift-evolution-announce] [Review] SE-0164: Remove final support in protocol extensions

Howard Lovatt howard.lovatt at gmail.com
Wed May 3 04:03:00 CDT 2017


@Goffredo,

Sorry I think we are at cross purposes. The *latest* version of the
proposal does allow ad-hoc code reuse by extensions where safe to do so.

Is that what you wanted?

  -- Howard.

On 3 May 2017 at 18:25, Goffredo Marocchi <panajev at gmail.com> wrote:

>
> Sent from my iPhone
>
> On 3 May 2017, at 09:15, Howard Lovatt <howard.lovatt at gmail.com> wrote:
>
> @Goffredo,
>
> "but while the core team has always stated "how else do we share code
> between structs/value types?" The proposal provides a way to do this safely
>
>
> My point is that overloading (pun half intended) protocols / protocol
> extensions to deliver that (it is not bad to desire not to have lots of
> boilerplate and/or duplicated code to share functionality across value
> types implementations) does create a scenario where the feature is not only
> dangerous, but incorrect too. I repeat myself often, but I fail to see how
> anyone would see casting changing the execution path as a positive (unless
> they are looking for ammunition to get rid of OOP ;)).
>
>   -- Howard.
>
> On 3 May 2017 at 17:33, Goffredo Marocchi <panajev at gmail.com> wrote:
>
>>
>>
>> Sent from my iPhone
>>
>> On 3 May 2017, at 08:25, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> I definitely agree that it's a feature that _can_ be used unwisely, but
>> the fact remains that it _is_ used pervasively in the standard library, and
>> deliberately, and that such uses have gone through Swift Evolution and been
>> approved.
>>
>>
>> I think there is still sense in discussing it if we care about the
>> language. I do agree that it is more likely and pragmatic (than removing it
>> outright) to have a warning about it that people can turn on and treat as
>> an error if they so choose, but while the core team has always stated "how
>> else do we share code between structs/value types?" essentially, I am not
>> sure why this should be allowed by default on class/reference types.
>> To me it just does not make sense and it is a dangerous compromise we
>> have and a regression from Objective-C.
>>
>> So there is really no point in discussing the removal of the feature, as
>> it simply cannot happen.
>> On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev at gmail.com> wrote:
>>
>>>
>>>
>>> Sent from my iPhone
>>>
>>> On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>> I don't understand your response. The standard library distinguishes
>>> between protocol requirements with default implementations, which can be
>>> overridden, and protocol extension methods, which can only be shadowed but
>>> not overridden. It is used pervasively, from integers to collections. For
>>> example, you can shadow but not override Sequence.contains. This is a
>>> deliberate design choice. You are describing this as "undesirable";
>>> however, it is not only highly desired (as expressed by many on this list
>>> every time a proposal to change it has come up), it would be impossible to
>>> maintain the current design of the standard library without this
>>> distinction.
>>>
>>>
>>> Being able to forbid overriding is fine, allowing shadowing without a
>>> compiler warning/error is undesirable though. We should not have to dig up
>>> 80's discussions about polymorphism to see that changing the actual code
>>> being executed by casting a reference one way or the other is wrong. It may
>>> be instrumentally good for some odd reason to someone, but I cannot see it
>>> as intrinsically good.
>>>
>>> Shadowing a method in a class declared in a protocol extension, where it
>>> also receives its default implementation, means that casting the instance
>>> of the class to the class type or the protocol type would have different
>>> methods being executed which can easily lead to mistakes beyond just
>>> appearing confusing and wrong.
>>>
>>> (let alone that IMHO protocols/interfaces are meant to decouple code and
>>> API contract and by definition shouldn't really have code in them, but it
>>> is convenient for us as we need to share code between value types...).
>>>
>>> In your new design, how would you express a protocol which has some
>>> requirements that have default implementations which can be overridden and
>>> some implemented methods that cannot be overridden? If the answer is that
>>> you cannot do that, then there is a problem.
>>> On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt at gmail.com>
>>> wrote:
>>>
>>>> You raise three points:
>>>>
>>>>   1. The harm is the inconsistent behaviour of extensions for both
>>>> structs and classes, as outlined in the first section of the proposal. This
>>>> is confusing for beginners and difficult to debug in large code bases,
>>>> particularly those involving third party libraries were source is not
>>>> available. I think a lot of the current experience with Swift does not use
>>>> large code bases or third party libraries because the experience is with
>>>> App development. As Swift moves to the server side large code bases and
>>>> third party libraries will become the norm and the problems that result
>>>> from the inconsistent behaviour will be magnified.
>>>>
>>>>   2. I am not saying that the current inconsistent behaviour is a bug I
>>>> am saying it is undesirable. The Generics Manifesto also lists the
>>>> behaviour as undesirable. Changes can and should be made for undesirable
>>>> behaviour, e.g. the exclusivity proposal currently under review and the
>>>> scoping of private which has been approved already.
>>>>
>>>>   3. I don't think making the changes required would be that large and
>>>> the payoff of enabling large code bases and third party libraries is huge.
>>>> The changes would involve:
>>>>
>>>>     i. Moving some extensions from a seperate file into the file were
>>>> the type was declared. This is good practice anyway and consistent with the
>>>> behaviour of private, so no big deal. You should be doing this anyway. This
>>>> would hardly affect the standard library.
>>>>
>>>>     ii. Removing declarations from protocols that have implementations
>>>> in extensions to *that* protocol. Easily caught by the compiler and Xcode
>>>> could do the refactoring.
>>>>
>>>>     ii. Marking retrospective conformance via extensions with final.
>>>> Because this also means that the methods need to be final there could be
>>>> some change. However, I would argue change for the good since it clarifies
>>>> what happens, much like the changes needed for exclusivity are good. Note
>>>> that since enum and struct methods are already final there is no change
>>>> here other than adding final. Again a small change that the compiler/Xcode
>>>> can do. The only area likely to have any issues are retrospective
>>>> conformance for protocols and classes. This is a small price to pay for
>>>> something as valuable as using third party libraries.
>>>>
>>>>
>>>> -- Howard.
>>>>
>>>> On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>
>>>> I'm sorry, it's been a while. What is the harm that you are trying to
>>>> cure, and how does this design accomplish that task?
>>>>
>>>> What you call "unexpected" is intentional. Many protocols, including
>>>> the revised integer protocols that were just approved, distinguish between
>>>> protocol requirements for which default implementations are provided and
>>>> protocol extension methods which can be shadowed but not overridden. Both
>>>> are used, and deliberately. Are you proposing to remove this feature? That
>>>> simply cannot be done, as it would require re-designing vast amounts of the
>>>> standard library that were just re-designed.
>>>>
>>>>
>>>> On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt at gmail.com>
>>>> wrote:
>>>>
>>>>> I haven't replied to these messages for a while since it has taken
>>>>> some time to formulate a proposal that incorporates the feedback give -
>>>>> thanks for the feedback.
>>>>>
>>>>> The new proposal allows retroactively added protocols to be exported
>>>>> and ad-hoc code reuse, the two areas of concern.
>>>>>
>>>>> Comments?
>>>>>
>>>>> ============================================================
>>>>> =====================
>>>>>
>>>>> # Proposal: Split extension into implementing methods and adding
>>>>> methods and protocols retrospectively
>>>>>
>>>>> ## Revision history
>>>>>
>>>>> | Version | Date               | Comment       |
>>>>> |---------|--------------|--------------|
>>>>> | Draft 1   | 11 April 2017 | Initial version |
>>>>> | Draft 2  | 13 April 2017 | Added support for post-hoc conformance to
>>>>> a protocol - replaced static final extensions with final extensions |
>>>>> | Draft 3 | 17 April 2017 | Added justification section |
>>>>> | Draft 4 | 2 May 2017   | Allow final extensions to be public and
>>>>> allow ad-hoc code reuse |
>>>>>
>>>>> ## Introduction
>>>>>
>>>>> Currently extension methods are confusing because they have different
>>>>> dispatch rules for the same calling syntax. EG:
>>>>>
>>>>>     public protocol P {
>>>>>         func mP() -> String
>>>>>      }
>>>>>     extension P {
>>>>>         func mP() -> String { return "P.mP" }
>>>>>         func mE() -> String { return "P.mE" }
>>>>>     }
>>>>>     struct S: P {
>>>>>         func mP() -> String { return "S.mP" }
>>>>>         func mE() -> String { return "S.mE" }
>>>>>     }
>>>>>     let s = S()
>>>>>     s.mP() // S.mP as expected
>>>>>     s.mE() // S.mE as expected
>>>>>     let p: P = s // Note: s now typed as P
>>>>>     p.mP() // S.mP as expected
>>>>>     p.mE() // P.mE unexpected!
>>>>>
>>>>> The situation with classes is even more confusing:
>>>>>
>>>>>     class C: P { /*gets the protocol extensions*/ }
>>>>>     let pC: P = C()
>>>>>     pC.mP() // P.mP as expected!
>>>>>     pC.mE() // P.mE as expected!
>>>>>     class D: C {
>>>>>         /*override not allowed!*/ func mP() -> String { return "D.mP" }
>>>>>         /*override not allowed!*/ func mE() -> String { return "D.mE" }
>>>>>     }
>>>>>     let pD: P = D()
>>>>>     pD.mP() // P.mP unexpected!
>>>>>     pD.mE() // P.mE unexpected!
>>>>>
>>>>> This proposal cures the above two problem by separating extension
>>>>> methods into two seperate use cases: implementations for methods and adding
>>>>> methods and protocols retrospectively. The proposal still retains
>>>>> retroactively adding protocol conformance and ad-hoc code reuse, however
>>>>> these are made easy to understand and safe.
>>>>>
>>>>> ## Implementing methods in same file as type declaration
>>>>>
>>>>> If the extension is in the **same** file as the type declaration then
>>>>> its implemented methods are dispatched using a Vtable for protocols and
>>>>> classes and statically for structs and enums. EG:
>>>>>
>>>>> File P.swift
>>>>>
>>>>>     protocol P {
>>>>>         // func m() not declared in type since it is added by the
>>>>> extension, under this proposal it is an error to include a declaration in a
>>>>> type **and** in an extension
>>>>>     }
>>>>>     extension P {
>>>>>         func m() { print("P.m") } // m is added to the protocol
>>>>> declaration
>>>>>     }
>>>>>
>>>>> Same or another file
>>>>>
>>>>>     struct S: P {
>>>>>         override func m() { print("S.m") } // Note override required
>>>>> because m already has an implementation from the extension
>>>>>     }
>>>>>     let p: P = S() // Note typed as P
>>>>>     p.m() // Now prints S.m as expected
>>>>>
>>>>> Extensions in the same file as the declaration can have any access,
>>>>> can be final, and can have where clauses and provide inheritable
>>>>> implementations. Ad-hoc code reuse is supported, in particular if a
>>>>> class/enum/strict already had a method, m say, and a protocol, P say,
>>>>> required an m then an extension that added P would not need to provide m
>>>>> (i.e. as at present).
>>>>>
>>>>> In a protocol at present you can declare a method that is then
>>>>> implemented in an extension without the use of the override keyword. This
>>>>> situation only applies to protocols, for structs/enumerated/classes you
>>>>> cannot declare in type and implement in an extension at all. This proposal
>>>>> unifies the behaviour of protocol/struct/enum/class with extensions and
>>>>> also prevents the error of a minor typo between the protocol and extension
>>>>> adding two methods instead of generating an error, by requiring either:
>>>>>
>>>>>   1. The method is only declared in the protocol and not in any
>>>>> extensions and is therefore abstract
>>>>>   2. The method is only in one extension and not in the protocol
>>>>>
>>>>> A method can be abstract in one protocol and implemented in a second
>>>>> protocol that extends the first.
>>>>>
>>>>> The implementation needed to achieve this proposal for a protocol is
>>>>> that a value instance typed as a protocol is copied onto the heap, a
>>>>> pointer to its Vtable added, and its address passed/copied (i.e. it becomes
>>>>> a class instance). No change is needed for a class instance typed as a
>>>>> protocol, which unlike at present can now be passed/copied as a protocol
>>>>> directly. Think of a protocol as like an abstract class; cannot be
>>>>> instantiated like an abstract class and which possibly has abstract
>>>>> methods, but in different in that it cannot have fields but can be multiply
>>>>> inherited.
>>>>>
>>>>> Static and final methods implemented in extensions are not part of the
>>>>> Vtable and are statically dispatched, i.e. no change from current Swift for
>>>>> static but final now has the expected meaning for a protocol. Dispatching
>>>>> for structs and classes unchanged.
>>>>>
>>>>> ## Retrospectively adding protocols and methods
>>>>>
>>>>> A new type of extension is proposed, a `final extension`, which can be
>>>>> either in or outside the file in which the protocol/struct/enum/class
>>>>> declaration is in:
>>>>>
>>>>> File P.swift
>>>>>
>>>>>     protocol P {}
>>>>>     extension P {
>>>>>         func m() { print("P.m") } // m is added to the protocol
>>>>> declaration
>>>>>     }
>>>>>
>>>>> Same or another file
>>>>>
>>>>>     struct S: P {} // Inherits m from the extension
>>>>>
>>>>> In file P2.swift
>>>>>
>>>>>     protocol P2 {
>>>>>         func m2()
>>>>>         func m() // Note same signature as P.m which S already
>>>>> implements
>>>>>     }
>>>>>
>>>>> In same or another file
>>>>>
>>>>>     final extension S: P2 { // Note extension marked final
>>>>>         // m cannot be provided because S already has a final m (the
>>>>> inherited method must be final)
>>>>>         func m2() { print("SP2.m2") } // Implicitly final, completes
>>>>> implementation of P2
>>>>>         func mE() { print("SP2.mE") } // Implicitly final, not an
>>>>> existing method
>>>>>     }
>>>>>
>>>>> Which are called as any other method would be called:
>>>>>
>>>>>     let s = S() // or S() as P2 or s: P2
>>>>>     s.m() // Prints S.m
>>>>>     s.m2() // Prints SP2.m2
>>>>>     s.mE() // Prints SP2.mE
>>>>>
>>>>> Notes:
>>>>>
>>>>>   1. A method added by a `final extension`, e.g. `mE`, is implicitly
>>>>> final (as the name would suggest).
>>>>>
>>>>>   2. If the `final extension` adds a method, e.g. `mE`, that method
>>>>> cannot already exist. IE a `final extension` cannot override an existing
>>>>> method or implement a protocol declared method that lacks an implementation
>>>>> (unless it also adds the protocol). This is retroactively adding a method.
>>>>> Also see next point.
>>>>>
>>>>>   3. If the `final extension` adds a protocol, e.g. `P2`, then it must
>>>>> implement all the methods in that protocol that are not  implemented, e.g.
>>>>> `m2`. This is retroactively adding protocol conformance. Also see next
>>>>> point.
>>>>>
>>>>>   4. If the `final extension` adds a protocol, e.g. `P2`, then it
>>>>> inherits all the methods in that protocol that are implemented, e.g. `m`.
>>>>> These inherited methods must be final. This is ad-hoc code reuse of final
>>>>> methods when retroactively adding protocol conformance.
>>>>>
>>>>> Final-extensions can have `where` clauses.
>>>>>
>>>>> The implementation for a `final extension` is always static
>>>>> dispatching. That is why all methods involved in a `final extension` are
>>>>> final. The compiler always knows that the method can be called statically
>>>>> and there is no need for a Vtable entry for any of the methods, it is as
>>>>> though the methods were declared static but with the more convenient syntax
>>>>> of a normal method.
>>>>>
>>>>> ## Justification
>>>>>
>>>>> The aim of Swift is nothing more than dominating the world. Using the
>>>>> current, April 2017, https://www.tiobe.com/tiobe-index/ index of job
>>>>> adverts for programmers the languages that are in demand are: Java 15.568%,
>>>>> C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
>>>>> .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
>>>>> Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
>>>>> new language and is already above Objective-C at 14th. However there is
>>>>> obviously a long way to go and the purpose of this proposal is to help with
>>>>> this climb.
>>>>>
>>>>> A characteristic of many of the languages above Swift in the Tiobe
>>>>> Index is that they have major third party libraries; for some languages
>>>>> they are almost defined by their third part libraries, e.g. Ruby for Rails.
>>>>> A major part of this proposal is to make extensions safe when using
>>>>> multiple libraries from different venders. In particular, the two forms of
>>>>> extensions in this proposal can safely be exported.
>>>>>
>>>>> As part of Swift's goal of world domination is that it is meant to be
>>>>> easy to learn by a process of "successive disclosure". The current
>>>>> inconsistent behaviour of protocols and extensions hinders this process and
>>>>> is a common gotcha for newbies. This proposal eliminates that problem also.
>>>>>
>>>>> Extensions are not new in languages, they are part of the .NET
>>>>> languages for example. Since .NET popularised extensions they have been
>>>>> discussed by other language communities, particularly Java and Scala, and
>>>>> in the academic community (normally termed the Expression Problem) however
>>>>> they have not proved popular because of the problems they cause. Nearly all
>>>>> languages have a strong bias towards keeping the language small and simple
>>>>> and trade of the advantages of a feature against the disadvantages. The
>>>>> feature only makes it into the language if it offers many advantages, has
>>>>> few disadvantages, and is not heavily overlapping with other features. It
>>>>> is this keeping it small and simple test that extensions have failed in
>>>>> other languages, in particular their behaviour is hard to predict in a
>>>>> large code base with multiple third party libraries.
>>>>>
>>>>> However, extensions are popular in Swift and this proposals makes a
>>>>> few changes to them to make their behaviour predictable both in terms of
>>>>> third party libraries and in terms of method dispatch when the variable is
>>>>> typed as a protocol. Thereby still providing extensions including
>>>>> retroactive conformance and ad-hoc code reuse, but without the problems.
>>>>>
>>>>> ## Possible future work (not part of this proposal)
>>>>>
>>>>> This proposal will naturally allow bodies to be added to protocols
>>>>> directly rather than via an extension, since under the proposal the
>>>>> extension adds the declaration to the type so it is a small step to allow
>>>>> the protocol methods to have an implementation.
>>>>>
>>>>> In an opposite sense to the above adding bodies to protocols,
>>>>> extensions could be allowed to add method declarations without bodies to
>>>>> protocols.
>>>>>
>>>>> The two above future work proposals, if both added, would add symmetry
>>>>> to where declarations and bodies may appear for protocols.
>>>>>
>>>>> ## In summary
>>>>>
>>>>> The proposal formalises the split use of extensions into their two
>>>>> uses: implementing methods and retroactively adding protocols and methods
>>>>> (in both cases including ad-hoc code reuse). The purpose of this split is
>>>>> to eliminate the problems associated with exceptions that have been well
>>>>> documented both with respect to Swift and other languages. Syntax is added
>>>>> that clarifies their two use cases (implementing methods and retroactively
>>>>> adding):
>>>>>
>>>>>   1. The former are termed extensions and must be in the same file as
>>>>> the type is declared, but can have non-final or final methods.
>>>>>   2. The latter are termed final-extensions and can be in any file,
>>>>> however final-extensions only have final methods.
>>>>>
>>>>> Note the distinction between an extension in the same file and in a
>>>>> separate file is consistent with the philosophy that there is special
>>>>> status to the same file as proposed for private in <
>>>>> http://github.com/apple/swift-evolution/blob/master/proposa
>>>>> ls/0169-improve-interaction-between-private-declarations-
>>>>> and-extensions.md>.
>>>>>
>>>>> ============================================================
>>>>> =====================
>>>>>
>>>>> On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42 at icloud.com>
>>>>> wrote:
>>>>>
>>>>>> +1
>>>>>>
>>>>>> Extensions are a great feature and I’m really glad that Swift has
>>>>>> them. Conflicts should be handled by improving import and disambiguation
>>>>>> features like Xiaodi says which is useful for other cases as well.
>>>>>>
>>>>>> -Thorsten
>>>>>>
>>>>>>
>>>>>> Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution <
>>>>>> swift-evolution at swift.org>:
>>>>>>
>>>>>> Simple: you put the user code that needs the more accurate library in
>>>>>> one file and import only the more accurate library there, and you put the
>>>>>> user code that needs the more performant library in a separate file and
>>>>>> import only the more performant library there! Swift's devotion to
>>>>>> file-based organization presents endless avenues of flexibility!
>>>>>>
>>>>>> What you write is an argument for designing a more expressive import
>>>>>> and/or disambiguation feature, not for disallowing public retroactive
>>>>>> conformance. A proposal to rip out entirely the ability to vend public APIs
>>>>>> with extensions is simply not going to fly. The core team has committed to
>>>>>> a small standard library and multiple independent core libraries like
>>>>>> Foundation. This can only work because Foundation can greatly expand the
>>>>>> API of standard library types through extensions.
>>>>>>
>>>>>> Your proposal would undo that design decision and require folding
>>>>>> Foundation's functionality into the standard library, or rewriting the
>>>>>> entire Foundation overlay to encapsulate standard library types instead of
>>>>>> extending them. For example, NSString would have to be a separate type that
>>>>>> encapsulates String. Yet oodles of work have gone into making NSString
>>>>>> seamlessly bridge to String in the first place.
>>>>>> On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt at gmail.com>
>>>>>> wrote:
>>>>>>
>>>>>>> Comments in-line below
>>>>>>>
>>>>>>> -- Howard.
>>>>>>>
>>>>>>> On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>>>>>>
>>>>>>> This continues to forbid use cases that are critical.
>>>>>>>
>>>>>>>
>>>>>>> I think "critical" is overstating the importance. Plenty of
>>>>>>> successful languages do not have extensions. Extensions have been discussed
>>>>>>> and rejected by successful languages. The .NET guidelines suggest
>>>>>>> considered cautious use. I have tried to encapsulate the best practice into
>>>>>>> a language feature.
>>>>>>>
>>>>>>>
>>>>>>> For instance, I am writing a library that vends additional
>>>>>>> conformances for Float and Double. Any numerics library would need to do
>>>>>>> the same.
>>>>>>>
>>>>>>>
>>>>>>> You need to consider this carefully because your numerics library
>>>>>>> might add a method sinh for example and the user of your library might be
>>>>>>> using other numerical libraries as well, one of these others might also
>>>>>>> provide sinh. Which is to be called in the user code by f.sinh? Suppose one
>>>>>>> library emphasises speed over accuracy and the other vice versa. You really
>>>>>>> want access to both versions in the user code. This is a situation I have
>>>>>>> come across a few times in numeric C, Java, and C++ with matrix libraries
>>>>>>> where code I have worked on has used multiple libraries in the same
>>>>>>> application for good reason.
>>>>>>>
>>>>>>> I think you would be better vending functions for things like sinh,
>>>>>>> rather than extending float with an additional function, and vending types
>>>>>>> for more complex things like matrices, rather than extending arrays with
>>>>>>> dot products for example. If you vend a type you can easily give access to
>>>>>>> the underlying type using composition rather than extension or inheritance,
>>>>>>> there is an example of this in the proposal just above the Justification
>>>>>>> section..
>>>>>>>
>>>>>>>
>>>>>>> Your design would eliminate all such libraries, which is a
>>>>>>> non-starter. I am not sure what defects you are trying to solve with this
>>>>>>> proposal.
>>>>>>>
>>>>>>> I am trying to make Swift more consistent, easier to learn, and to
>>>>>>> encourage third-party libraries.
>>>>>>>
>>>>>>>
>>>>>>> On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> @Brent,
>>>>>>>>
>>>>>>>> I have updated the proposal to address your concerns, in particular
>>>>>>>> I don't see that retrospectively adding methods and protocols has been
>>>>>>>> removed it has just had its ugly corners rounded. See revised proposal
>>>>>>>> below particularly the end of section "Retrospectively adding
>>>>>>>> protocols and methods" and new section "Justification".
>>>>>>>>
>>>>>>>> Hope this convinces you that the change is worthwhile.
>>>>>>>>
>>>>>>>> -- Howard.
>>>>>>>>
>>>>>>>> ====================================
>>>>>>>>
>>>>>>>> # Proposal: Split extension usage up into implementing methods and
>>>>>>>> adding methods and protocols retrospectively
>>>>>>>>
>>>>>>>> ## Revision history
>>>>>>>> | Version | Date               | Comment       |
>>>>>>>> |---------|--------------|--------------|
>>>>>>>> | Draft 1   | 11 April 2017 | Initial version |
>>>>>>>> | Draft 2  | 13 April 2017 | Added support for post-hoc conformance
>>>>>>>> to a protocol - replaced static final extensions with final extensions |
>>>>>>>> | Draft 3 | 17 April 2017 | Added justification section |
>>>>>>>>
>>>>>>>> ## Introduction
>>>>>>>>
>>>>>>>> Currently extension methods are confusing because they have
>>>>>>>> different dispatch rules for the same calling syntax. EG:
>>>>>>>>
>>>>>>>>     public protocol P {
>>>>>>>>         func mP() -> String
>>>>>>>>      }
>>>>>>>>     extension P {
>>>>>>>>         func mP() -> String { return "P.mP" }
>>>>>>>>         func mE() -> String { return "P.mE" }
>>>>>>>>     }
>>>>>>>>     struct S: P {
>>>>>>>>         func mP() -> String { return "S.mP" }
>>>>>>>>         func mE() -> String { return "S.mE" }
>>>>>>>>     }
>>>>>>>>     let s = S()
>>>>>>>>     s.mP() // S.mP as expected
>>>>>>>>     s.mE() // S.mE as expected
>>>>>>>>     let p: P = s // Note: s now typed as P
>>>>>>>>     p.mP() // S.mP as expected
>>>>>>>>     p.mE() // P.mE unexpected!
>>>>>>>>
>>>>>>>> Extension methods can also cause compatibility problems between
>>>>>>>> modules, consider:
>>>>>>>>
>>>>>>>> In Module A
>>>>>>>>     extension Int: P {
>>>>>>>>         func m() -> String { print("A.m") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> In Module B
>>>>>>>>     extension Int: P {
>>>>>>>>         func m() -> String { print("B.m") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> In Module C
>>>>>>>>     import A
>>>>>>>>     import B // Should this be an error
>>>>>>>>     let i = 0
>>>>>>>>     i.m() // Should it return A.m or B.m?
>>>>>>>>
>>>>>>>> This proposal cures the above two problems by separating extension
>>>>>>>> methods into two seperate use cases: implementations for methods and adding
>>>>>>>> methods and protocols retrospectively.
>>>>>>>>
>>>>>>>> ## Implementing methods
>>>>>>>>
>>>>>>>> If the extension is in the same file as the
>>>>>>>> protocol/struct/enum/class declaration then it implements the methods and
>>>>>>>> is dispatched using a Vtable. EG:
>>>>>>>>
>>>>>>>> File P.swift
>>>>>>>>     protocol/struct/enum/class P {
>>>>>>>>         // func m() not declared in type since it is added by the
>>>>>>>> extension, under this proposal it is an error to include a declaration in a
>>>>>>>> type *and* in an extension
>>>>>>>>     }
>>>>>>>>     extension P {
>>>>>>>>         func m() { print("P.m") } // m is added to the
>>>>>>>> protocol/struct/enum/class declaration
>>>>>>>>     }
>>>>>>>>
>>>>>>>> Same or other file
>>>>>>>>     struct S: P {
>>>>>>>>         override func m() { print("S.m") } // Note override
>>>>>>>> required because m already has an implementation from the extension
>>>>>>>>     }
>>>>>>>>     let p: P = S() // Note typed as P
>>>>>>>>     p.m() // Now prints S.m as expected
>>>>>>>>
>>>>>>>> Extensions in the same file as the declaration can have any access,
>>>>>>>> can be final, and can have where clauses and provide inheritable
>>>>>>>> implementations.
>>>>>>>>
>>>>>>>> In a protocol at present there is a difference in behaviour between
>>>>>>>> a protocol that declares a method that is then implemented in an extension
>>>>>>>> and a protocol that just has the method implemented in an extension and no
>>>>>>>> declaration. This situation only applies to protocols, for
>>>>>>>> structs/enumerated/classes you cannot declare in type and implement in
>>>>>>>> extensions. The proposal unifies the behaviour of
>>>>>>>> protocol/struct/enum/class with extensions and prevents the error of a
>>>>>>>> minor typo between the protocol and extension adding two methods instead of
>>>>>>>> generating an error.
>>>>>>>>
>>>>>>>> The implementation needed to achieve this proposal is that a value
>>>>>>>> instance typed as a protocol is copied onto the heap, a pointer to its
>>>>>>>> Vtable added, and it is passed as a pointer. IE it becomes a class
>>>>>>>> instance. No change needed for a class instance typed as a protocol.
>>>>>>>>
>>>>>>>> ## Retrospectively adding protocols and methods
>>>>>>>>
>>>>>>>> A new type of extension is proposed, a "final extension", which can
>>>>>>>> be either in or outside the file in which the protocol/struct/enum/class
>>>>>>>> declaration is in. EG:
>>>>>>>>
>>>>>>>>     protocol P2 {
>>>>>>>>         func m2P()
>>>>>>>>     }
>>>>>>>>     final extension S: P2 { // Note extension marked final
>>>>>>>>         func m2P() { print("SP2.m2P") } // Implicitly final,
>>>>>>>> completely implements P2
>>>>>>>>         func m2E() { print("SP2.m2E") } // Implicitly final, not an
>>>>>>>> existing method
>>>>>>>>     }
>>>>>>>>
>>>>>>>> Which are called as any other method would be called:
>>>>>>>>
>>>>>>>>     let s = S()
>>>>>>>>     s.m2P() // Prints SP2.m2P
>>>>>>>>     s.m2E() // Prints SP2.m2E
>>>>>>>>
>>>>>>>> A method added by a final extension is is implicitly final, as the
>>>>>>>> name would suggest, and cannot be overridden.
>>>>>>>>
>>>>>>>> Notes:
>>>>>>>>
>>>>>>>>   1. If the final extension adds a method, e.g. m2E, that method
>>>>>>>> cannot already exist. IE a final extension cannot override an existing
>>>>>>>> method or implement a protocol declared method that lacks an implementation
>>>>>>>> unless it also adds the protocol.
>>>>>>>>
>>>>>>>>   2. If the final extension adds a protocol then it must implement
>>>>>>>> all the methods in that protocol that are not currently implemented.
>>>>>>>>
>>>>>>>>   3. If the final extension is outside of the file in which the
>>>>>>>> protocol/struct/enum/class declaration is in then the extension and the
>>>>>>>> methods can only have fileprivate or internal access. This prevents
>>>>>>>> retrospective extensions from numerous modules clashing, since they are not
>>>>>>>> exported outside of the module.
>>>>>>>>
>>>>>>>> When a type is extended inside a module with a final extension the
>>>>>>>> extension is not exported. For example:
>>>>>>>>
>>>>>>>>     final extension Int: P2 {
>>>>>>>>         func m2P() { print("Int.m2P") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> If an exported function uses Int, e.g.:
>>>>>>>>
>>>>>>>>     public func f(_ x: Int) -> Int {
>>>>>>>>         x.m2P()
>>>>>>>>         return x
>>>>>>>>     }
>>>>>>>>
>>>>>>>> Then when used in an external module both the input Int and the
>>>>>>>> output Int are not extended with P2. However as the Int goes into f it
>>>>>>>> gains P2 conformance and when it leaves it looses P2 conformance. Thus
>>>>>>>> inside and outside the module the behaviour is easily understood and
>>>>>>>> consistent and doesn't clash with other final extensions in other modules.
>>>>>>>>
>>>>>>>> Taking the above example further an Int with P2 conformance is
>>>>>>>> required by the user of a library; then it can simply and safely be
>>>>>>>> provided, e.g.:
>>>>>>>>
>>>>>>>>     public class P2Int: P2 {
>>>>>>>>         var value = 0
>>>>>>>>         func m2P() { print("Int.m2P") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> This type, P2Int, is easy to write, one line longer than a final
>>>>>>>> extension, and can easily be used as both a P2 and an Int and does not
>>>>>>>> clash with another Int extension from another module.
>>>>>>>>
>>>>>>>> ## Justification
>>>>>>>>
>>>>>>>> The aim of Swift is nothing more than dominating the world. Using
>>>>>>>> the current, April 2017, https://www.tiobe.com/tiobe-index/ index
>>>>>>>> of job adverts for programmers the languages that are in demand are: Java
>>>>>>>> 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual
>>>>>>>> Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl
>>>>>>>> 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well
>>>>>>>> for a new language and is already above Objective-C at 14th. However there
>>>>>>>> is obviously a long way to go and the purpose of this proposal is to help
>>>>>>>> with this climb.
>>>>>>>>
>>>>>>>> A characteristic of many of the languages above Swift in the Tiobe
>>>>>>>> Index is that they have major third party libraries; for some languages
>>>>>>>> they are almost defined by their third part libraries, e.g. Ruby for Rails.
>>>>>>>> A major part of this proposal is to make extensions safe when using
>>>>>>>> multiple libraries from different venders. In particular final extensions
>>>>>>>> are not exported.
>>>>>>>>
>>>>>>>> As part of Swift's goal of world domination is that it is meant to
>>>>>>>> be easy to learn by a process of "successive disclosure". The current
>>>>>>>> inconsistent behaviour of protocols and extensions hinders this process and
>>>>>>>> is a common gotcha for newbies. This proposal eliminates that problem also.
>>>>>>>>
>>>>>>>> Extensions are not new in languages, they are part of the .NET
>>>>>>>> languages for example. Since .NET popularised extensions they have been
>>>>>>>> discussed by other language communities, particularly Java and Scala, and
>>>>>>>> in the academic community (normally termed the Expression Problem) however
>>>>>>>> they have not proved popular because of the problems they cause. Nearly all
>>>>>>>> languages have a strong bias towards keeping the language small and simple
>>>>>>>> and trade of the advantages of a feature against the disadvantages and the
>>>>>>>> feature only makes it into the language if it offers many advantages, has
>>>>>>>> few disadvantages, and is not heavily overlapping with other features. This
>>>>>>>> keeping it small and simple test is what extensions have failed in other
>>>>>>>> languages.
>>>>>>>>
>>>>>>>> Experience from .NET can however be used to improve extensions.
>>>>>>>> There is some excellent advice https://blogs.msdn.microsoft.c
>>>>>>>> om/vbteam/2007/03/10/extension-methods-best-practices-
>>>>>>>> extension-methods-part-6/ written by the VB .NET team when they
>>>>>>>> added extensions to VB .NET. The best-practice advice can be summarised by
>>>>>>>> the following quotes from the reference:
>>>>>>>>
>>>>>>>>   0. "In most real world applications these suggestions [the rest
>>>>>>>> of the suggestions] can (and quite frankly should!) be completely ignored."
>>>>>>>> This is an important observations, in your own code that is not intended
>>>>>>>> for reuse; go for it, use extensions. The proposal importantly still allows
>>>>>>>> this style of programming and in fact improves it by adding consistent
>>>>>>>> behaviour and syntax between protocols/structs/enumerated/classes.
>>>>>>>>
>>>>>>>>  1. "Read the .NET Framework Class Library Design Guidelines." The
>>>>>>>> equivalent for Swift is lacking at this stage. Probably because third party
>>>>>>>> libraries are rare.
>>>>>>>>
>>>>>>>>   2. "Be wary of extension methods." This recommendation is
>>>>>>>> formalised in the proposal by limiting final extensions to be fileprivate
>>>>>>>> or internal.
>>>>>>>>
>>>>>>>>   3. "Put extension methods into their own namespace." This
>>>>>>>> recommendation is formalised in the proposal by limiting final extensions
>>>>>>>> to be fileprivate or internal.
>>>>>>>>
>>>>>>>>   4. "Think twice before extending types you don’t own."
>>>>>>>>
>>>>>>>>   5. "Prefer interface extensions over class extensions."
>>>>>>>> Translation to Swift terminology provide default implementations for
>>>>>>>> protocol methods. The proposal encourages this by eliminating a major
>>>>>>>> gotcha with the current implementation, namely the proposal always
>>>>>>>> dispatches via a Vtable to give consistent behaviour.
>>>>>>>>
>>>>>>>>   6. "Be as specific with the types you extend as possible."
>>>>>>>> Translation to Swift terminology provide default implementations for
>>>>>>>> protocol methods that extend other  protocols if there is a more specific
>>>>>>>> behaviour that is relevent. The proposal encourages this by eliminating a
>>>>>>>> major gotcha with the current implementation, namely the proposal always
>>>>>>>> dispatches via a Vtable to give consistent behaviour.
>>>>>>>>
>>>>>>>> The proposal formalises these best practices from .NET whilst
>>>>>>>> increasing consistence and without loosing the ability to use extensions
>>>>>>>> heavily in your own one-off code to allow for rapid development. Most of
>>>>>>>> the best practices are for better libraries, particularly third party,
>>>>>>>> which is an important area for future Swift growth onto the server side.
>>>>>>>> This proposal actively encourages this transition to large formal server
>>>>>>>> side code without loosing the free wheeling nature of app code.
>>>>>>>>
>>>>>>>> ## Possible future work (not part of this proposal)
>>>>>>>>
>>>>>>>> This proposal will naturally allow bodies to be added to protocols
>>>>>>>> directly rather than via an extension, since under the proposal the
>>>>>>>> extension adds the declaration to the type so it is a small step to allow
>>>>>>>> the protocol methods to have an implementation.
>>>>>>>>
>>>>>>>> In an opposite sense to the above adding bodies to protocols,
>>>>>>>> extensions could be allowed to add method declarations without bodies to
>>>>>>>> protocols.
>>>>>>>>
>>>>>>>> The two above future work proposals, if both added, would add
>>>>>>>> symmetry to where declarations and bodies may appear for protocols.
>>>>>>>>
>>>>>>>> ## In summary.
>>>>>>>>
>>>>>>>> The proposal formalises the split use of extensions into their two
>>>>>>>> uses: implementing methods and post-hoc adding protocols and methods.
>>>>>>>> Syntax is added that clarifies the two use cases, the former are termed
>>>>>>>> extensions and must be in the same file as the type is declared, and the
>>>>>>>> latter are termed final extensions and can be in any file, however if they
>>>>>>>> are not in the type's file the they can only have fileprivate or internal
>>>>>>>> access.
>>>>>>>>
>>>>>>>> Note the distinction between an extension in the same file and in a
>>>>>>>> separate file is consistent with the philosophy that there is special
>>>>>>>> status to the same file as proposed for private in
>>>>>>>> https://github.com/apple/swift-evolution/blob/master/proposa
>>>>>>>> ls/0169-improve-interaction-between-private-declarations-
>>>>>>>> and-extensions.md.
>>>>>>>>
>>>>>>>> ===================================================
>>>>>>>>
>>>>>>>> #Proposal: Split extension usage up into implementing methods and
>>>>>>>> adding methods and protocols post-hoc
>>>>>>>>
>>>>>>>> Draft 2 (Added support for post-hoc conformance to a protocol -
>>>>>>>> replaced static final extensions with final extensions)
>>>>>>>>
>>>>>>>> ## Introduction
>>>>>>>>
>>>>>>>> Currently extension methods are confusing because they have
>>>>>>>> different dispatch rules for the same calling syntax. EG:
>>>>>>>>
>>>>>>>>     public protocol P {
>>>>>>>>         func mP() -> String
>>>>>>>>      }
>>>>>>>>     extension P {
>>>>>>>>         func mP() -> String { return "P.mP" }
>>>>>>>>         func mE() -> String { return "P.mE" }
>>>>>>>>     }
>>>>>>>>     struct S: P {
>>>>>>>>         func mP() -> String { return "S.mP" }
>>>>>>>>         func mE() -> String { return "S.mE" }
>>>>>>>>     }
>>>>>>>>     let s = S()
>>>>>>>>     s.mP() // S.mP as expected
>>>>>>>>     s.mE() // S.mE as expected
>>>>>>>>     let p: P = s // Note: s now typed as P
>>>>>>>>     p.mP() // S.mP as expected
>>>>>>>>     p.mE() // P.mE unexpected!
>>>>>>>>
>>>>>>>> Extension methods can also cause compatibility problems between
>>>>>>>> modules, consider:
>>>>>>>>
>>>>>>>> In Module A
>>>>>>>>     extension Int: P {
>>>>>>>>         func m() -> String { print("A.m") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> In Module B
>>>>>>>>     extension Int: P {
>>>>>>>>         func m() -> String { print("B.m") }
>>>>>>>>     }
>>>>>>>>
>>>>>>>> In Module C
>>>>>>>>     import A
>>>>>>>>     import B // Should this be an error
>>>>>>>>     let i = 0
>>>>>>>>     i.m() // Should it return A.m or B.m?
>>>>>>>>
>>>>>>>> This proposal cures the above two problems by separating extension
>>>>>>>> methods into two seperate use cases: implementations for methods and adding
>>>>>>>> methods and protocols post-hoc.
>>>>>>>>
>>>>>>>> ## Implementing methods
>>>>>>>>
>>>>>>>> If the extension is in the same file as the protocol/struct/class
>>>>>>>> declaration then it implements the methods and is dispatched using a
>>>>>>>> Vtable. EG:
>>>>>>>>
>>>>>>>> File P.swift
>>>>>>>>     protocol/struct/class P {
>>>>>>>>         // func m() not declared in type since it is added by the
>>>>>>>> extension, under this proposal it is an error to include a declaration in a
>>>>>>>> type *and* in an extension
>>>>>>>>     }
>>>>>>>>     extension P {
>>>>>>>>         func m() { print("P.m") } // m is added to the
>>>>>>>> protocol/struct/class declaration
>>>>>>>>     }
>>>>>>>>
>>>>>>>> Same or other file
>>>>>>>>     struct S: P {
>>>>>>>>         override func m() { print("S.m") } // Note override
>>>>>>>> required because m already has an implementation from the extension
>>>>>>>>     }
>>>>>>>>     let p: P = S() // Note typed as P
>>>>>>>>     p.m() // Now prints S.m as expected
>>>>>>>>
>>>>>>>> Extensions in the same file as the declaration can have any access,
>>>>>>>> can be final, and can have where clauses and provide inheritable
>>>>>>>> implementations.
>>>>>>>>
>>>>>>>> In a protocol at present there is a difference in behaviour between
>>>>>>>> a protocol that declares a method that is then implemented in an extension
>>>>>>>> and a protocol that just has the method implemented in an extension and no
>>>>>>>> declaration. This situation only applies to protocols, for structs and
>>>>>>>> classes you cannot declare in type and implement in extensions. The
>>>>>>>> proposal unifies the behaviour of protocol/struct/class with extensions and
>>>>>>>> prevents the error of a minor typo between the protocol and extension
>>>>>>>> adding two methods instead of generating an error.
>>>>>>>>
>>>>>>>> The implementation needed to achieve this is that a value instance
>>>>>>>> typed as a protocol is copied onto the heap, a pointer to its Vtable added,
>>>>>>>> and it is passed as a pointer. IE it becomes a class instance. No change
>>>>>>>> needed for a class instance typed as a protocol.
>>>>>>>>
>>>>>>>> ## Post-hoc adding protocols and methods
>>>>>>>>
>>>>>>>> A new type of extension is proposed, a "final extension", which can
>>>>>>>> be either in or outside the file in which the protocol/struct/class
>>>>>>>> declaration is in. EG:
>>>>>>>>
>>>>>>>>     protocol P2 {
>>>>>>>>         func m2P()
>>>>>>>>     }
>>>>>>>>     final extension S: P2 { // Note extension marked final
>>>>>>>>         func m2P() { print("SP2.m2P") } // Implicitly final,
>>>>>>>> completely implements P2
>>>>>>>>         func m2E() { print("SP2.m2E") } // Implicitly final, not an
>>>>>>>> existing method
>>>>>>>>     }
>>>>>>>>
>>>>>>>> Which are called as any other method would be called:
>>>>>>>>
>>>>>>>>     let s = S()
>>>>>>>>     s.m2P() // Prints SP2.m2P
>>>>>>>>     s.m2E() // Prints SP2.m2E
>>>>>>>>
>>>>>>>> A method added by a final extension is is implicitly final, as the
>>>>>>>> name would suggest, and cannot be overridden.
>>>>>>>>
>>>>>>>> If the final extension:
>>>>>>>>
>>>>>>>>   1. Adds a method, e.g. m2E, that method cannot already exist. IE
>>>>>>>> a final extension cannot override an existing method or implement a
>>>>>>>> protocol declared method that lacks an implementation unless it also
>>>>>>>> post-hoc adds the protocol.
>>>>>>>>
>>>>>>>>   2. Adds a protocol then it must implement all the methods in that
>>>>>>>> protocol that are not currently implemented.
>>>>>>>>
>>>>>>>>   3. Is outside of the file in which the protocol/struct/class
>>>>>>>> declaration is in then the extension and the methods can only have
>>>>>>>> fileprivate or internal access. This prevents post-hoc extensions from
>>>>>>>> numerous modules clashing, since they are not exported outside of the
>>>>>>>> module.
>>>>>>>>
>>>>>>>> ## Possible future work (not part of this proposal)
>>>>>>>>
>>>>>>>> This proposal will naturally allow bodies to be added to protocols
>>>>>>>> directly rather than via an extension, since under the proposal the
>>>>>>>> extension adds the declaration to the type so it is a small step to allow
>>>>>>>> the protocol methods to have an implementation.
>>>>>>>>
>>>>>>>> In an opposite sense to the above adding bodies to protocols,
>>>>>>>> extensions could be allowed to add method declarations without bodies to
>>>>>>>> protocols.
>>>>>>>>
>>>>>>>> The two above future work proposals, if both added, would add
>>>>>>>> symmetry to where declarations and bodies may appear for protocols.
>>>>>>>>
>>>>>>>> ## In summary.
>>>>>>>>
>>>>>>>> The proposal formalises the split use of extensions into their two
>>>>>>>> uses: implementing methods and post-hoc adding protocols and methods.
>>>>>>>> Syntax is added that clarifies the two use cases, the former are termed
>>>>>>>> extensions and must be in the same file as the type is declared, and the
>>>>>>>> latter are termed final extensions and can be in any file, however if they
>>>>>>>> are not in the type's file the they can only have fileprivate or internal
>>>>>>>> access.
>>>>>>>>
>>>>>>>> Note the distinction between an extension in the same file and in a
>>>>>>>> separate file is consistent with the philosophy that there is special
>>>>>>>> status to the same file as proposed for private in
>>>>>>>> https://github.com/apple/swift-evolution/blob/master/proposa
>>>>>>>> ls/0169-improve-interaction-between-private-declarations-
>>>>>>>> and-extensions.md.
>>>>>>>>
>>>>>>>>
>>>>>>>> ====================================
>>>>>>>>
>>>>>>>> On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <
>>>>>>>> brent at architechies.com> wrote:
>>>>>>>>
>>>>>>>> On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <
>>>>>>>> swift-evolution at swift.org> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> I don't see that retroactive conformance needs to be exportable. If
>>>>>>>> it is exported then you cannot prevent clashes from two modules, this is a
>>>>>>>> known problem in C#. Because of this and other problems with C# extensions,
>>>>>>>> this style of extension were rejected by other language communities
>>>>>>>> (notably Java and Scala).
>>>>>>>>
>>>>>>>>
>>>>>>>> A better alternative for export is a new class that encapsulates
>>>>>>>> the standard type but with added methods for the protocol to be added. This
>>>>>>>> way there is no clash between modules. EG:
>>>>>>>>
>>>>>>>>
>>>>>>>>    public protocol P {
>>>>>>>>
>>>>>>>>        func m() -> String
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>>    public class PInt: P {
>>>>>>>>
>>>>>>>>        var value = 0
>>>>>>>>
>>>>>>>>        func m() -> String { return "PI.m" }
>>>>>>>>
>>>>>>>>    }
>>>>>>>>
>>>>>>>>
>>>>>>>> Howard, this would be very source-breaking and would fail to
>>>>>>>> achieve fundamental goals of Swift's protocol design. Removing retroactive
>>>>>>>> conformance is no more realistic than removing Objective-C bridging—another
>>>>>>>> feature which introduces various ugly edge cases and tricky behaviors but
>>>>>>>> is also non-negotiable.
>>>>>>>>
>>>>>>>> --
>>>>>>>> Brent Royal-Gordon
>>>>>>>> Architechies
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>> swift-evolution mailing list
>>>>>> swift-evolution at swift.org
>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>>>>
>>>>>> --
>>>>> -- Howard.
>>>>>
>>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170503/b34f204f/attachment-0001.html>


More information about the swift-evolution mailing list