<div>I&#39;m sorry, it&#39;s been a while. What is the harm that you are trying to cure, and how does this design accomplish that task?</div><div><br></div><div>What you call &quot;unexpected&quot; 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.</div><div><br></div><div><br><div class="gmail_quote"><div>On Tue, May 2, 2017 at 02:54 Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com">howard.lovatt@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div>I haven&#39;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. </div><div><br></div><div>The new proposal allows retroactively added protocols to be exported and ad-hoc code reuse, the two areas of concern.</div><div><br></div><div>Comments?</div><div><br></div><div>=================================================================================</div><div><br></div><div><div># Proposal: Split extension into implementing methods and adding methods and protocols retrospectively</div></div><div><div><br></div><div>## Revision history</div><div><br></div><div>| Version | Date               | Comment       |</div><div>|---------|--------------|--------------|</div><div>| Draft 1   | 11 April 2017 | Initial version |</div><div>| Draft 2  | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |</div><div>| Draft 3 | 17 April 2017 | Added justification section |</div></div><div><div>| Draft 4 | 2 May 2017   | Allow final extensions to be public and allow ad-hoc code reuse |</div></div><div><div><br></div><div>## Introduction</div><div><br></div><div>Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:</div><div><br></div><div>    public protocol P {</div><div>        func mP() -&gt; String</div><div>     }</div><div>    extension P {</div><div>        func mP() -&gt; String { return &quot;P.mP&quot; }</div><div>        func mE() -&gt; String { return &quot;P.mE&quot; }</div><div>    }</div><div>    struct S: P {</div><div>        func mP() -&gt; String { return &quot;S.mP&quot; }</div><div>        func mE() -&gt; String { return &quot;S.mE&quot; }</div><div>    }</div><div>    let s = S()</div><div>    s.mP() // S.mP as expected</div><div>    s.mE() // S.mE as expected</div><div>    let p: P = s // Note: s now typed as P</div><div>    p.mP() // S.mP as expected</div><div>    p.mE() // P.mE unexpected!</div><div>    </div></div><div><div>The situation with classes is even more confusing:</div><div><br></div><div>    class C: P { /*gets the protocol extensions*/ }</div><div>    let pC: P = C()</div><div>    pC.mP() // P.mP as expected!</div><div>    pC.mE() // P.mE as expected!</div><div>    class D: C {</div><div>        /*override not allowed!*/ func mP() -&gt; String { return &quot;D.mP&quot; }</div><div>        /*override not allowed!*/ func mE() -&gt; String { return &quot;D.mE&quot; }</div><div>    }</div><div>    let pD: P = D()</div><div>    pD.mP() // P.mP unexpected!</div><div>    pD.mE() // P.mE unexpected!</div><div><br></div><div>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. </div><div><br></div><div>## Implementing methods in same file as type declaration </div><div><br></div><div>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:</div><div><br></div><div>File P.swift</div><div><br></div><div>    protocol P {</div><div>        // 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</div><div>    }</div><div>    extension P {</div><div>        func m() { print(&quot;P.m&quot;) } // m is added to the protocol declaration</div><div>    }</div><div><br></div><div>Same or another file</div></div><div><div><br></div><div>    struct S: P {</div><div>        override func m() { print(&quot;S.m&quot;) } // Note override required because m already has an implementation from the extension</div><div>    }</div><div>    let p: P = S() // Note typed as P</div><div>    p.m() // Now prints S.m as expected </div><div><br></div></div><div><div>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).</div><div><br></div><div>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:</div><div><br></div><div>  1. The method is only declared in the protocol and not in any extensions and is therefore abstract</div><div>  2. The method is only in one extension and not in the protocol</div><div><br></div><div>A method can be abstract in one protocol and implemented in a second protocol that extends the first. </div><div><br></div><div>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. </div><div><br></div><div>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.</div></div><div><div><br></div><div>## Retrospectively adding protocols and methods</div><div><br></div></div><div><div>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:</div><div><br></div><div>File P.swift</div><div><br></div><div>    protocol P {}</div><div>    extension P {</div><div>        func m() { print(&quot;P.m&quot;) } // m is added to the protocol declaration</div><div>    }</div><div><br></div><div>Same or another file</div><div><br></div><div>    struct S: P {} // Inherits m from the extension </div><div><br></div><div>In file P2.swift</div><div><br></div><div>    protocol P2 {</div><div>        func m2()</div><div>        func m() // Note same signature as P.m which S already implements</div><div>    }</div><div>    </div><div>In same or another file</div></div><div><div>    </div><div>    final extension S: P2 { // Note extension marked final</div></div><div><div>        // m cannot be provided because S already has a final m (the inherited method must be final)</div><div>        func m2() { print(&quot;SP2.m2&quot;) } // Implicitly final, completes implementation of P2</div><div>        func mE() { print(&quot;SP2.mE&quot;) } // Implicitly final, not an existing method</div></div><div><div>    }</div><div><br></div><div>Which are called as any other method would be called:</div><div><br></div></div><div><div>    let s = S() // or S() as P2 or s: P2</div><div>    s.m() // Prints S.m</div><div>    s.m2() // Prints SP2.m2</div><div>    s.mE() // Prints SP2.mE</div><div><br></div><div>Notes:</div><div><br></div><div>  1. A method added by a `final extension`, e.g. `mE`, is implicitly final (as the name would suggest). </div><div><br></div><div>  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.</div><div><br></div><div>  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.</div><div><br></div><div>  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. </div><div><br></div><div>Final-extensions can have `where` clauses. </div><div><br></div><div>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. </div></div><div><div><br></div><div>## Justification </div><div><br></div><div>The aim of Swift is nothing more than dominating the world. Using the current, April 2017, <a href="https://www.tiobe.com/tiobe-index/" target="_blank">https://www.tiobe.com/tiobe-index/</a> 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.</div><div><br></div></div><div><div>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.</div></div><div><div><br></div><div>As part of Swift&#39;s goal of world domination is that it is meant to be easy to learn by a process of &quot;successive disclosure&quot;. The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.</div><div><br></div></div><div><div>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.</div><div><br></div><div>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.</div></div><div><div><br></div><div>## Possible future work (not part of this proposal)</div><div><br></div><div>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. </div><div><br></div><div>In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols. </div><div><br></div><div>The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols. </div><div><br></div><div>## In summary</div><div><br></div></div><div><div>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):</div><div><br></div><div>  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.</div><div>  2. The latter are termed final-extensions and can be in any file, however final-extensions only have final methods.</div><div><br></div><div>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 &lt;<a href="http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md" target="_blank">http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md</a>&gt;.</div></div><div><br></div><div>=================================================================================</div><div><br><div class="gmail_quote"><div>On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz &lt;<a href="mailto:tseitz42@icloud.com" target="_blank">tseitz42@icloud.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">+1<div><br></div><div>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.<br><div><br></div><div>-Thorsten</div><div><br></div><div><br><div><blockquote type="cite"></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div>Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;:</div><br class="m_2262640237962007650m_2082244261578013179Apple-interchange-newline"></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div>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&#39;s devotion to file-based organization presents endless avenues of flexibility!<br><br>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.<br><br>Your proposal would undo that design decision and require folding Foundation&#39;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.<br><div class="gmail_quote"><div>On Mon, Apr 17, 2017 at 20:05 Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div><span></span></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185AppleMailSignature">Comments in-line below<br><br>-- Howard. </div></div></div></div><div><div><div><div><br>On 17 Apr 2017, at 9:01 am, Xiaodi Wu &lt;<a href="mailto:xiaodi.wu@gmail.com" target="_blank">xiaodi.wu@gmail.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div>This continues to forbid use cases that are critical.<br></div></blockquote><div><br></div></div></div></div><div><div><div><div>I think &quot;critical&quot; 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. </div></div></div></div><div><div><div><blockquote type="cite"><div><br>For instance, I am writing a library that vends additional conformances for Float and Double. Any numerics library would need to do the same.<br></div></blockquote><div><br></div></div></div></div><div><div><div><div>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. </div><div><br></div><div>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..</div></div></div></div><div><div><div><blockquote type="cite"><div><br>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.</div><div><br></div></blockquote></div></div></div><div><div><div>I am trying to make Swift more consistent, easier to learn, and to encourage third-party libraries.</div></div></div><div><div><div><br><blockquote type="cite"><div><br><div class="gmail_quote"><div>On Sun, Apr 16, 2017 at 17:51 Howard Lovatt &lt;<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>@Brent,</div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><br></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature">I have updated the proposal to address your concerns, in particular I don&#39;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 &quot;<span style="background-color:rgba(255,255,255,0)">Retrospectively adding protocols and methods&quot; and new section &quot;Justification&quot;.</span></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><br></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature">Hope this convinces you that the change is worthwhile.<br><br>-- Howard.</div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><br></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature">====================================</div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><br></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"># Proposal: Split extension usage up into implementing methods and adding methods and protocols retrospectively</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Revision history</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">| Version | Date               | Comment       |</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">|---------|--------------|--------------|</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">| Draft 1   | 11 April 2017 | Initial version |</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">| Draft 2  | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">| Draft 3 | 17 April 2017 | Added justification section |</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Introduction</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    public protocol P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">     }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String { return &quot;P.mP&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mE() -&gt; String { return &quot;P.mE&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    struct S: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String { return &quot;S.mP&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mE() -&gt; String { return &quot;S.mE&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let s = S()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.mP() // S.mP as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.mE() // S.mE as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let p: P = s // Note: s now typed as P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.mP() // S.mP as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.mE() // P.mE unexpected!</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Extension methods can also cause compatibility problems between modules, consider:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module A</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension Int: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() -&gt; String { print(&quot;A.m&quot;) }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module B</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension Int: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() -&gt; String { print(&quot;B.m&quot;) }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module C</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    import A</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    import B // Should this be an error</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let i = 0</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    i.m() // Should it return A.m or B.m?</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Implementing methods</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">File P.swift</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    protocol/struct/enum/class P {</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        // 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</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension P {</span></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() { print(&quot;P.m&quot;) } // m is added to the protocol/struct/enum/class declaration</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Same or other file</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    struct S: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        override func m() { print(&quot;S.m&quot;) } // Note override required because m already has an implementation from the extension</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let p: P = S() // Note typed as P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.m() // Now prints S.m as expected </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Retrospectively adding protocols and methods</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">A new type of extension is proposed, a &quot;final extension&quot;, which can be either in or outside the file in which the protocol/struct/enum/class declaration is in. EG:</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    protocol P2 {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    final extension S: P2 { // Note extension marked final</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P() { print(&quot;SP2.m2P&quot;) } // Implicitly final, completely implements P2</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2E() { print(&quot;SP2.m2E&quot;) } // Implicitly final, not an existing method</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Which are called as any other method would be called:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let s = S()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.m2P() // Prints SP2.m2P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.m2E() // Prints SP2.m2E</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Notes:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  2. If the final extension adds a protocol then it must implement all the methods in that protocol that are not currently implemented.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">When a type is extended inside a module with a final extension the extension is not exported. For example:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    final extension Int: P2 {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P() { print(&quot;Int.m2P&quot;) } </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">If an exported function uses Int, e.g.:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    public func f(_ x: Int) -&gt; Int {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        x.m2P()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        return x</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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&#39;t clash with other final extensions in other modules.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    public class P2Int: P2 {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        var value = 0</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P() { print(&quot;Int.m2P&quot;) }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Justification </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">The aim of Swift is nothing more than dominating the world. Using the current, April 2017, <a href="https://www.tiobe.com/tiobe-index/" target="_blank"><span style="font-size:17pt;color:rgb(228,175,10)">https://www.tiobe.com/tiobe-index/</span></a> 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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">As part of Swift&#39;s goal of world domination is that it is meant to be easy to learn by a process of &quot;successive disclosure&quot;. The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Experience from .NET can however be used to improve extensions. There is some excellent advice <a href="https://blogs.msdn.microsoft.com/vbteam/2007/03/10/extension-methods-best-practices-extension-methods-part-6/" target="_blank">https://blogs.msdn.microsoft.com/vbteam/2007/03/10/extension-methods-best-practices-extension-methods-part-6/</a> 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:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  0. &quot;In most real world applications these suggestions [the rest of the suggestions] can (and quite frankly should!) be completely ignored.&quot; 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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"> 1. &quot;Read the .NET Framework Class Library Design Guidelines.&quot; The equivalent for Swift is lacking at this stage. Probably because third party libraries are rare.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  2. &quot;Be wary of extension methods.&quot; This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  3. &quot;Put extension methods into their own namespace.&quot; This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  4. &quot;Think twice before extending types you don’t own.&quot; </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  5. &quot;Prefer interface extensions over class extensions.&quot; 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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  6. &quot;Be as specific with the types you extend as possible.&quot; 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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Possible future work (not part of this proposal)</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## In summary.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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&#39;s file the they can only have fileprivate or internal access.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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 <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md" target="_blank"><span style="font-size:17pt;color:rgb(228,175,10)">https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md</span></a>.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">===================================================</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">#Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Introduction</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    public protocol P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String</span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">     }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String { return &quot;P.mP&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mE() -&gt; String { return &quot;P.mE&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    struct S: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mP() -&gt; String { return &quot;S.mP&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func mE() -&gt; String { return &quot;S.mE&quot; }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let s = S()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.mP() // S.mP as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.mE() // S.mE as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let p: P = s // Note: s now typed as P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.mP() // S.mP as expected</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.mE() // P.mE unexpected!</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Extension methods can also cause compatibility problems between modules, consider:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module A</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension Int: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() -&gt; String { print(&quot;A.m&quot;) }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module B</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension Int: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() -&gt; String { print(&quot;B.m&quot;) }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In Module C</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    import A</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    import B // Should this be an error</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let i = 0</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    i.m() // Should it return A.m or B.m?</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Implementing methods</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">File P.swift</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    protocol/struct/class P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        // 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</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    extension P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m() { print(&quot;P.m&quot;) } // m is added to the protocol/struct/class declaration</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Same or other file</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    struct S: P {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        override func m() { print(&quot;S.m&quot;) } // Note override required because m already has an implementation from the extension</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let p: P = S() // Note typed as P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    p.m() // Now prints S.m as expected </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Post-hoc adding protocols and methods</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">A new type of extension is proposed, a &quot;final extension&quot;, which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    protocol P2 {</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    final extension S: P2 { // Note extension marked final</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2P() { print(&quot;SP2.m2P&quot;) } // Implicitly final, completely implements P2</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">        func m2E() { print(&quot;SP2.m2E&quot;) } // Implicitly final, not an existing method</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    }</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">Which are called as any other method would be called:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    let s = S()</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.m2P() // Prints SP2.m2P</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">    s.m2E() // Prints SP2.m2E</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div>
</div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden. </span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">If the final extension:</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  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.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">  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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## Possible future work (not part of this proposal)</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols. </span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">## In summary.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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&#39;s file the they can only have fileprivate or internal access.</span></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69);min-height:20.3px"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"></span><br></div><div style="margin:0px;line-height:normal;font-family:&#39;.SF UI Text&#39;;color:rgb(69,69,69)"><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt">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 <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md</a>.</span></div><div><span style="font-family:&#39;.SFUIText&#39;;font-size:17pt"><br></span></div></div></div><div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature"><br></div><div id="m_2262640237962007650m_2082244261578013179m_7963075272645824114m_4183725646821454185m_-2753664487318090949AppleMailSignature">====================================</div></div><div><div><br>On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon &lt;<a href="mailto:brent@architechies.com" target="_blank">brent@architechies.com</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><blockquote type="cite"><span>On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>I don&#39;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). </span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>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:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    public protocol P {</span><br></blockquote><blockquote type="cite"><span>        func m() -&gt; String</span><br></blockquote><blockquote type="cite"><span>    }</span><br></blockquote><blockquote type="cite"><span>    public class PInt: P {</span><br></blockquote><blockquote type="cite"><span>        var value = 0</span><br></blockquote><blockquote type="cite"><span>        func m() -&gt; String { return &quot;PI.m&quot; }</span><br></blockquote><blockquote type="cite"><span>    }</span><br></blockquote><span></span><br><span>Howard, this would be very source-breaking and would fail to achieve fundamental goals of Swift&#39;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.</span><br><span></span><br><span>-- </span><br><span>Brent Royal-Gordon</span><br><span>Architechies</span><br><span></span><br></div></blockquote></div></blockquote></div>
</div></blockquote></div></div></div></blockquote></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div>
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div></div></div></div></blockquote></div></div><div>-- <br></div><div data-smartmail="gmail_signature">-- Howard.</div>
</blockquote></div></div>