<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div>@Xiaodi,</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature">You can safely post-hoc add protocols and methods provided that they are final, do not override, and are not exported from the module. See version 2 of the proposal below. <br><br>-- Howard.</div><div id="AppleMailSignature"><br></div><div id="AppleMailSignature"><p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"># Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">## Introduction</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> public protocol P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func mP() -> String</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> extension P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func mP() -> String { return "P.mP" }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func mE() -> String { return "P.mE" }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> struct S: P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func mP() -> String { return "S.mP" }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func mE() -> String { return "S.mE" }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> let s = S()</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> s.mP() // S.mP as expected</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> s.mE() // S.mE as expected</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> let p: P = s // Note: s now typed as P</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> p.mP() // S.mP as expected</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> p.mE() // P.mE unexpected!</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">Extension methods can also cause compatibility problems between modules, consider:</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">In Module A</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> extension Int: P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m() -> String { print("A.m") }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">In Module B</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> extension Int: P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m() -> String { print("B.m") }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">In Module C</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> import A</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> import B // Should this be an error</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> let i = 0</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> i.m() // Should it return A.m or B.m?</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">## Implementing methods</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">File P.swift</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> protocol/struct/class P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> extension P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m() { print("P.m") } // m is added to the protocol/struct/class declaration</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">Same or other file</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> struct S: P {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> override func m() { print("S.m") } // Note override required because m already has an implementation from the extension</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> let p: P = S() // Note typed as P</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> p.m() // Now prints S.m as expected </span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">## Post-hoc adding protocols and methods</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> protocol P2 {</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m2P()</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> final extension S: P2 { // Note extension marked final</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> }</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">Which are called as any other method would be called:</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> let s = S()</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> s.m2P() // Prints SP2.m2P</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> s.m2E() // Prints SP2.m2E</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">A method added by a final extension is implicitly final, as the name would suggest, and cannot be overridden. </span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">If the final extension:</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;"> 2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">## Possible future work (not part of this proposal)</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; font-size: 17pt;">## In summary.</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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's file the they can only have fileprivate or internal access.</span></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69); min-height: 20.3px;"><span style="font-family: '.SFUIText'; font-size: 17pt;"></span><br></p>
<p style="margin: 0px; line-height: normal; font-family: '.SF UI Text'; color: rgb(69, 69, 69);"><span style="font-family: '.SFUIText'; 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">https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md</a>.</span></p></div><div><br>On 11 Apr 2017, at 1:26 pm, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com">xiaodi.wu@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div>As far as I'm aware, eliminating retroactive conformances is a non-starter.<br><br><br><div class="gmail_quote"><div dir="ltr">On Mon, Apr 10, 2017 at 21:44 Howard Lovatt <<a href="mailto:howard.lovatt@gmail.com">howard.lovatt@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div class="gmail_msg">@Xiaodi,</div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg"><br class="gmail_msg"></div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg">You make two drugs. </div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg"><br class="gmail_msg"></div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg">1. Deliberately making retroactive conformance outside of the file in which the type is declared illegal because of the problems it causes. See all the questions on Swift Users and watch people learning Swift get caught out. </div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg"><br class="gmail_msg"></div><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg">2. Outside of the file in which the type is declared the static final extension is restricted to internal or fileprivate so that multiple modules can add static final extensions without clashes. </div></div><div dir="auto" class="gmail_msg"><div id="m_3934634403776160645AppleMailSignature" class="gmail_msg"><br class="gmail_msg"><br class="gmail_msg">-- Howard. </div></div><div dir="auto" class="gmail_msg"><div class="gmail_msg"><br class="gmail_msg">On 11 Apr 2017, at 8:51 am, Xiaodi Wu <<a href="mailto:xiaodi.wu@gmail.com" class="gmail_msg" target="_blank">xiaodi.wu@gmail.com</a>> wrote:<br class="gmail_msg"><br class="gmail_msg"></div><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div dir="ltr" class="gmail_msg">On Mon, Apr 10, 2017 at 5:35 PM, Howard Lovatt via swift-evolution <span dir="ltr" class="gmail_msg"><<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br class="gmail_msg"><div class="gmail_extra gmail_msg"><div class="gmail_quote gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div class="gmail_msg">In response to Jordan Rose's comment I suggest the following change:</div><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg"><br class="gmail_msg"></div><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg"><p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">Proposal: Split extension usage up into implementing methods and adding static functions</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">Currently extension methods are confusing because they have different dispatch rules for the same syntax. EG:</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> protocol P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m()</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> extension P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m() { print("P.m") }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> struct S: P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m() { print("S.m") }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> val p: P = S() // Note typed as P</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> p.m() // Surprisingly prints P.m even though S implements its own m</span></p></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">This is incorrect. This prints "S.m", not "P.m".</div><div class="gmail_msg"> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg">
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> val s = S() // Note typed as S</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> s.m() // Prints S.m as expected </span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">This proposal cures the above problem by separating extension methods into two seperate use cases: implementations for methods and adding static functions. </span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">First implementing methods.</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">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></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">File P.swift</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> protocol/struct/class P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m()</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> extension P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m() { print("P.m") }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">Same or other file</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> struct S: P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> override func m() { print("S.m") } // Note override required because m already has an implementation from the extension</span></p></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Requiring `override` breaks retroactive conformance of types to protocols. This idea has been brought up over half a dozen times. Each time it fails in not being able to accommodate retroactive conformance.</div><div class="gmail_msg"> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg">
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> val p: P = S() // Note typed as P</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> p.m() // Now prints S.m as expected </span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">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></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">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></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">The second use case is adding static functions.</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">A new type of extension is proposed, a static final extension, which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> static final extension P { // Note extension marked static final</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> func m() { print("P.m") }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">Which is called as any other static function would be called:</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> val s = S()</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> P.m(s) // Prints P.m as expected</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">The new static final extension is shorthand, particularly in the case of multiple functions, for:</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> extension P {</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> static final func m(_ this: P) { print("P.m") }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"> }</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">If the static final extension is outside of the file in which the protocol/struct/class declaration is in then the extension and the methods can only have fileprivate and internal access.</span></p></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">What is the use case for having this restriction? What is the problem you are trying to solve? </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto" class="gmail_msg"><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg"><p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">As at present protocol/struct/class can have both a static and instance method of the same name, m in the case of the example, because the usage syntax is distinct. As at present, static final extensions, both the extension and the individual functions, can have where clauses.</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">In summary.</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">The proposal formalises the split use of extensions into their two uses: implementing methods and adding static functions. Syntax is added that clarifies both for declarations and usage which type of extension is provided/in use.</span></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69);min-height:20.3px" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg"></span><br class="gmail_msg"></p>
<p style="margin:0px;line-height:normal;font-family:'.SF UI Text';color:rgb(69,69,69)" class="gmail_msg"><span style="font-family:'.SFUIText';font-size:17pt" class="gmail_msg">Note the distinction between an extension in the same file and in a separate file is consistent with the proposed use of private in <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md</a>.</span></p><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg"><br class="gmail_msg"></div>Comments?</div><div id="m_3934634403776160645m_-5335225969984223547AppleMailSignature" class="gmail_msg"><br class="gmail_msg">-- Howard.</div><div class="gmail_msg"><br class="gmail_msg">On 7 Apr 2017, at 4:49 am, Jordan Rose <<a href="mailto:jordan_rose@apple.com" class="gmail_msg" target="_blank">jordan_rose@apple.com</a>> wrote:<br class="gmail_msg"><br class="gmail_msg"></div><blockquote type="cite" class="gmail_msg"><div class="gmail_msg"><div class="gmail_msg">[Proposal: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0164-remove-final-support-in-protocol-extensions.md" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/blob/master/proposals/0164-remove-final-support-in-protocol-extensions.md</a>]</div><br class="gmail_msg"><div class="gmail_msg"><blockquote type="cite" class="gmail_msg"><div class="gmail_msg">On Apr 5, 2017, at 16:15, Howard Lovatt via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_3934634403776160645m_-5335225969984223547Apple-interchange-newline gmail_msg"><div class="gmail_msg"><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg">The review of SE-0164 "Remove final support in protocol extensions"</span></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><br class="gmail_msg"></div><div style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class="gmail_msg"><blockquote type="cite" class="gmail_msg"><ul style="box-sizing:border-box;padding-left:2em;margin-top:0px;margin-bottom:16px" class="gmail_msg"><li style="box-sizing:border-box" class="gmail_msg"><font class="gmail_msg"><span style="background-color:rgba(255,255,255,0)" class="gmail_msg">What is your evaluation of the proposal?</span></font></li></ul></blockquote><div class="gmail_msg">The present situation isn't great. People get confused about which method will called with protocol extensions. Seems like every week there is a variation on this confusion on Swift Users mailing list. Therefore something needs to be done. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">However I am not keen on this proposal since it makes behaviour inconsistent between methods in protocol extensions, classes, and structs. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I think a better solution would be one of the following alternatives:</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg"> 1. Must use final and final means it cannot be overridden; or</div><div class="gmail_msg"> 2. If not final dispatches using a table like a class and if marked final cannot be overridden and if marked dynamic uses obj-c dispatching; or</div><div class="gmail_msg"> 3. Must be marked dynamic and uses obj-c dispatching. </div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">My preference would be option 2 but I think any of the three is superior to the present situation or the proposal. </div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">People have suggested all of these before, but none of them are obviously correct. It's true that we have a difference between extension members that satisfy requirements and those that don't, and that that confuses people. However, an extension-only member of one protocol can be used to satisfy the requirements of another protocol today, which is a tool for code reuse.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">(I <i class="gmail_msg">think</i> we managed to convince everyone that it's just a bug that a protocol extension method that satisfies a requirement cannot be overridden in a subclass, so at least that isn't an issue on top of the rest of this.)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Oh, and we can't retroactively add members of a protocol extension to existing adopters, which is why protocol extension members cannot be @objc. There are limited circumstances where that would be safe, but that would be a separate proposal.</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">Jordan</div></div></div></blockquote></div><br class="gmail_msg">_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
<br class="gmail_msg"></blockquote></div><br class="gmail_msg"></div></div>
</div></blockquote></div></blockquote></div>
</div></blockquote></body></html>