How is retroactive modeling accommodated in this scheme? Say I want to conform three types I don't own to a protocol of my design and supply a default implementation for a protocol requirement. How would I go about it? On Thu, Apr 28, 2016 at 11:53 Erica Sadun via swift-evolution < [email protected]> wrote:
> Draft. Criticism and suggestions both welcome. -- E > > Requiring Proactive Overrides for Default Protocol Implementations > > - Proposal: tbd > - Author(s): Erica Sadun <http://github.com/erica> > - Status: tbd > - Review manager: tbd > > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#introduction> > Introduction > > This proposal enhances protocol implementation safety. It incorporates two > keywords that cooperate with compiler checks to limit "near miss" > implementation errors and accidental member overrides. > > *This proposal was discussed on the Swift Evolution list in the [Pitch] > Requiring proactive overrides for default protocol implementations. > <http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496> thread* > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#motivation> > Motivation > > The proposal introduces a mandatory required keyword that marks members > as fulfiling protocol requirements. This expansion reduces the risk of > near-miss implementations (for example, adding thud(x: Double) when thud(x: > Float)is required), provides in-line documentation of why the member has > been included, thereby enhancing the code-level documentation at the > implementation point, and supports compile-time checks for protocol > conformance. > > This proposal extends the override keyword to protocol conformance. The > Swift Programming Language describes the way subclass methods must override > implementations established in superclasses. *Methods on a subclass that > override the superclass’s implementation are marked with > **override**—overriding > a method by accident, without override, is detected by the compiler as an > error. The compiler also detects methods with override that don’t actually > override any method in the superclass.* > > Adding an override requirement expands this cautious approach to > protocols. Developers must override implementations inherited from protocol > extensions with the override keyword. And the compiler will flag uses of > override where member implementations do not, in fact, override an > existing implementation. The keyword prevents accidental overrides, where a > sensible member name conflicts with signatures established in the protocol > conformance and forces users to proactively select a version in favor of > existing protocol extensions. > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#detail-design>Detail > Design > > - The override keyword is extended to protocol inheritance, and when > used prefers the overridden behavior to the default behavior. > - Swift will prefer an overridden implementation in preference in > reverse hierarchical order: type extensions take precedence over type > declarations over protocol extensions over protocol declarations (assuming > protocol declarations eventually adopt default implementations). > - The required keyword marks a member as satisfying a protocol > requirement, whether in protocol extensions, type declarations, or type > extensions. > > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#required-protocol-members>Required > Protocol Members > > Protocol requirements are marked with required for compile-time checks of > intentional conformance. > > protocol A { > func foo() > func bar() > func blort() > func gar() > } > extension A { > required func blort() {} // Correct, required by `A` > func womble() {} // Correct, new method in extension > func gar() {} // Incorrect: Compiler says: add `required` keyword or > remove implementation > } > struct B: A { > required func foo() {} // Correct > required func far() {} // Near miss. Compiler: rename method or drop > required keyword > func bar() {} // Possible accidental name match. Compiler: rename method > or add required keyword > } > > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#member-overrides>Member > Overrides > > Overrides are marked with override to ensure intent. > > protocol A { > func foo() > func bar() > func blort() > func gar() > } > extension A { > required func foo() {} // correct > func womble() {} // correct > } > struct B: A { > required func bar() {} // correct > required func foo() {} // incorrect: Compiler says: add `override` > keyword or remove implementation > func womble() {} // incorrect: Compiler says add `override` keyword or > remove implementation. `required` is not needed as `womble` is not a required > protocol member. > } > > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#handling-changes>Handling > Changes > > Default implementations can be added or removed at any time, as can type > conformance implementations: > **Original** **Change** **Outcome** > Some member implemented in type Protocol adds that member Must add > `required` to type implementation or rename member to avoid conflict > Some member implemented in type, marked as `required` Protocol removes > that member or it never existed Must remove `required` from type > implementation > Some member implemented in type, marked as `override` Protocol extension > removes that member or it never existed Must remove `override` from type > implementation > Some member implemented in typed, member not mentioned in protocol Extension > adds default version of member Type implementation must add `override` > keyword > `required` member implemented in type Default member added Must add > `override` or remove type implementation > `override required` member implemented in type Remove default member Must > remove `override` in type implementation > `override required` member implemented in type Remove type member > implementation Default implementation now used > Type member uses `required` keyword Protocol removes requirement or never > had it Type implementation must remove `required` keyword > Protocol declares required member Extension implements default > implementation Extension must add `required` keyword, differentiating > default implementations from added behavior > Swift adds default implementations to protocols as well as extensions Protocol > adds default implementation Type implementation must use both `required` > and `override` keywords. Protocol extension must use `override` keyword. > Order of preference goes: overriden member, overriden extension, protocol > default implementation > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#multiple-conformance-conflict>Multiple > Conformance Conflict > > Consider the following situation. For the sake of future-proofing, this > example includes default protocol implementations although they do not yet > exist in Swift. > > protocol A { func foo() {...default...} }protocol B { func foo() > {...default...} }extension A { override required func foo() {...A > extension...} }Type CType: A, B {} > > In this example, the compiler emits a warning that "CType cannot > unambiguously differentiate which version of foo to use for CType instances". > If the CType type were to be removed or either of its conformances erased, > there would be no compiler issues. > > To fix this scenario, CType must implement a version of foo that resolves > the conflict: > > Type CType: A, B { override required func foo() { > // either > A.foo(self)() // uses the A extension default implementation > // or > B.foo(self)() // uses the B protocol default implementation > // or both, one after the other, etc. > } > > In this rewrite, foo is unambiguously referenced for CType instance > members. > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#impact-on-existing-code>Impact > on Existing Code > > These changes introduce mandates that do not exist in today's Swift code > and will require migration. The migrator (and compiler) must detect both > scenarios: that a member satisfies a protocol requirement and needs the > required keyword, and that a member overrides a default implementation > (in current Swift, only in extensions) and needs the overridekeyword. > > In the degenerate case that protocol extensions provide two distinct > default implementations of the same member (whether required or not), the > override version should always be preferred. When multiple override versions > exist, the compiler should emit a warning about ambiguous resolution. > > Using type currying, e.g. A.foo(self) should always resolve using the > rules enumerated earlier in this proposal, moving from type extensions to > types to protocol extension to protocols. > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#alternatives-considered>Alternatives > Considered > > Not at this time. > > <https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a#acknowledgements-and-thanks>Acknowledgements > and Thanks > Thanks, Doug Gregor, Jordan Rose, and Joe Groff > > > > > On Apr 27, 2016, at 6:07 PM, Douglas Gregor <[email protected]> wrote: > > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution >
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
