On Mon, Apr 10, 2017 at 5:35 PM, Howard Lovatt via swift-evolution < swift-evolution@swift.org> wrote:
> In response to Jordan Rose's comment I suggest the following change: > > Proposal: Split extension usage up into implementing methods and adding > static functions > > > Currently extension methods are confusing because they have different > dispatch rules for the same syntax. EG: > > > protocol P { > > func m() > > } > > extension P { > > func m() { print("P.m") } > > } > > struct S: P { > > func m() { print("S.m") } > > } > > val p: P = S() // Note typed as P > > p.m() // Surprisingly prints P.m even though S implements its own m > This is incorrect. This prints "S.m", not "P.m". > val s = S() // Note typed as S > > s.m() // Prints S.m as expected > > > This proposal cures the above problem by separating extension methods into > two seperate use cases: implementations for methods and adding static > functions. > > > First implementing methods. > > > If the extension is in the same file as the protocol/struct/class > declaration then it implements the methods and is dispatched using a > Vtable. EG: > > > File P.swift > > protocol/struct/class P { > > func m() > > } > > extension P { > > func m() { print("P.m") } > > } > > > Same or other file > > struct S: P { > > override func m() { print("S.m") } // Note override required > because m already has an implementation from the extension > 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. > } > > val p: P = S() // Note typed as P > > p.m() // Now prints S.m as expected > > > Extensions in the same file as the declaration can have any access, can be > final, and can have where clauses and provide inheritable implementations. > > > 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. > > > The second use case is adding static functions. > > > 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: > > > static final extension P { // Note extension marked static final > > func m() { print("P.m") } > > } > > > Which is called as any other static function would be called: > > > val s = S() > > P.m(s) // Prints P.m as expected > > > The new static final extension is shorthand, particularly in the case of > multiple functions, for: > > > extension P { > > static final func m(_ this: P) { print("P.m") } > > } > > > 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. > What is the use case for having this restriction? What is the problem you are trying to solve? > 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. > > > In summary. > > > 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. > > > Note the distinction between an extension in the same file and in a > separate file is consistent with the proposed use of private in > https://github.com/apple/swift-evolution/blob/master/ > proposals/0169-improve-interaction-between-private- > declarations-and-extensions.md. > > Comments? > > -- Howard. > > On 7 Apr 2017, at 4:49 am, Jordan Rose <jordan_r...@apple.com> wrote: > > [Proposal: https://github.com/apple/swift-evolution/blob/ > master/proposals/0164-remove-final-support-in-protocol-extensions.md] > > On Apr 5, 2017, at 16:15, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote: > > The review of SE-0164 "Remove final support in protocol extensions" > > > - What is your evaluation of the proposal? > > 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. > > However I am not keen on this proposal since it makes behaviour > inconsistent between methods in protocol extensions, classes, and structs. > > I think a better solution would be one of the following alternatives: > > 1. Must use final and final means it cannot be overridden; or > 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 > 3. Must be marked dynamic and uses obj-c dispatching. > > My preference would be option 2 but I think any of the three is superior > to the present situation or the proposal. > > > 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. > > (I *think* 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.) > > 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. > > Jordan > > > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution