[Pitch] Requiring proactive overrides for default protocol implementations.

Hey, what annotations would I have in this case:

Module 1:
Type AType { func foo() { ... } }
Module 2:
import Module1
protocol A { func foo() {...default...} }
extension AType: A {}

No annotations. AType's implementation of foo is unrelated to its conformance, which is satisfied by its existing foo method.

How does this match the first line in your "Handling Changes" table?

(from your table, for reference)
Original: Some member implemented in type
Change: Protocol adds that member
Outcome: Must add 'required' to type implementation or rename member to avoid conflict

···

On Apr 28, 2016, at 20:51, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 28, 2016, at 6:44 PM, Andrew Bennett <cacoyi@gmail.com> wrote:

Also, for your alternatives section:

protocol A { func foo() {...default...} }
Type AType: A {
    func A.foo() {...replacement...}
}

I actually prefer this alternative, I think it fixes many issues.

Protocol default implementations do not yet exist.

In this second, you're suggesting instead of doing "override required", you use a naming approach that ties the implementation the specific protocol. I'm not really won over by this approach:

* It does clarify why the method is included
* It does not clarify that the method overrides an existing implementation.
* It could be more easily confused when members are required by multiple protocols.

-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Thanks for clarifying, my responses are inline.

Hey, what annotations would I have in this case:

Module 1:

Type AType { func foo() { ... } }

Module 2:

import Module1protocol A { func foo() {...default...} }extension AType: A {}

No annotations. AType's implementation of foo is unrelated to its
conformance, which is satisfied by its existing foo method.

Thanks, that resolves my misunderstanding. I thought there would need to be
an override or similar.

Also, for your *alternatives* section:

protocol A { func foo() {...default...} }Type AType: A {
    func A.foo() {...replacement...}
}

I actually prefer this alternative, I think it fixes many issues.

Protocol default implementations do not yet exist.

In this second, you're suggesting instead of doing "override required",
you use a naming approach that ties the implementation the specific
protocol. I'm not really won over by this approach:

* It does clarify why the method is included
* It does not clarify that the method overrides an existing implementation.

I agree with this, your `override` keyword would work well here.

* It could be more easily confused when members are required by multiple

protocols.

I see this as a feature. I think this member should *only* implement it for
a single protocol.

If you have the same member in multiple protocols, then they potentially
(probably) do different things. They may want different implementations. If
the member is meant to represent the same thing, then it should be
extracted into a common protocol.

···

On Fri, Apr 29, 2016 at 10:51 AM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 28, 2016, at 6:44 PM, Andrew Bennett <cacoyi@gmail.com> wrote:

-- E

Sorry, that's not my question, which doesn't involve protocols I don't own. Let me restate. Given three types I don't own as follows:

struct A : Frobnicate {
    override required func frobnicate() { print("A") } // "A", or delete to get default
}
struct B: Frobnicate {
    override required func frobnicate() { print("B") } // "B", or delete to get default
}
struct C: Frobnicate  { }

These are a couple of derived situations:

struct IAssumeThisIsAProblem : Frobnicate {
    required func frobnicate() { print("A") }
}

struct IAssumeThisIsAnotherProblem Frobnicate {
    override func frobnicate() { print("A") }
}

What happens in both cases?

···

On Apr 28, 2016, at 8:09 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

-- E

On Apr 28, 2016, at 11:48 AM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Sorry, that's not my question, which doesn't involve protocols I don't own. Let me restate. Given three types I don't own as follows:

struct A {
    func frobnicate() { print("A") }
}
struct B {
    func frobnicate() { print("B") }
}
struct C { }

I want to conform them to a protocol of my own design, Frobnicatable, and supply a default `frobnicate()`:

protocol Frobnicatable {
    func frobnicate()
}
extension Frobnicatable {
    func frobnicate() { print("Default") }
}
extension A: Frobnicatable { }
extension B: Frobnicatable { }
extension C: Frobnicatable { }

let c = C()
c.frobnicate() // "Default"

(Yes, I realize there are issues regarding static and dynamic dispatch that limit the utility of this particular example--let's leave those aside for now.)
Where would I affix keywords such as `required` and `override` to make this work after implementation of your proposal?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Hi Erica, could you clarify, what is state of this proposal and your plans regarding it? I believe we certainly should make Swift more explicit regarding what methods in type are required by the conformed protocol and what methods are required(and which are 'optional') in protocol extensions.

Right now there is a discussion regarding 'optional' keyword("Modify optional method semantics for swift"), and I remembered your proposal..

Probably 'optional' keyword for non-required methods in extension instead of marking 'required' methods will looks better(as they are optional to the protocol itself), what do you think?
I.e.

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..

     func blort() {} // Correct, was introduced in `A`
     optional func womble() {} // Correct, new(optional) method in extension
     optional func gar() {} // Incorrect: Compiler says: remove `optional`..
}

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

     func womble() {} // ?? how this method should be 'marked' ??
}

(But personally I think one *overload* keyword will do the job in both cases - in extension and in type declaration)

Regarding this "func womble()" questions.. I think we need *at least* compilation warning that *at the moment of compilation*, B.womble may(?) conflicts with extension of A.womble.

Personaly I was not expecting to get the result of this code:

protocol A {
   func a()
}

extension A {
    func b() { print("(b) in A") }
}

struct C : A {
     func a() {}
     func b() { print("(b) in C") }
}

var c : A = C()
c.b() // (b) in A

···

On 28.04.2016 19:53, Erica Sadun via swift-evolution 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&gt;
  * Status: tbd
  * Review manager: tbd2

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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&gt; thread/

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

    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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

        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
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

        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.
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

        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

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

        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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

    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 |override|keyword.

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

    Considered

Not at this time.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

    and Thanks

Thanks, Doug Gregor, Jordan Rose, and Joe Groff

On Apr 27, 2016, at 6:07 PM, Douglas Gregor <dgregor@apple.com >>> <mailto:dgregor@apple.com>> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I've arrived at the "just table it and find something more productive to work on" stage. This pitch grew out of my conviction that doing "near miss" detection was the wrong approach for supporting and documenting developer intent decisions. If there's no strong support my the core concept (enhancing safety by introducing semantic compiler hints) then all the implementation details in the world don't get me anywhere.

Without developing a quorum that supports the underlying philosophy, regardless of implementation, I'm not going to push this any further. The gist is updated but I have no plans to further mold it into a proposal.

-- E

···

On Apr 28, 2016, at 10:00 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Hi, Erica. Sorry for not participating in the first round here. I’m…not so happy with this direction, for a number of reasons. (I apologize for the laundry list, but they’re not really related complaints.)

- ‘required’ already means something today: it means “this initializer must be present on all subclasses”. The reason it only applies to initializers is because all other members are always present on all subclasses.

(Counter-argument: using ‘required’ on an initializer could be seen as making an implicit protocol, just for that class hierarchy.)

- ‘override’ likewise already has a meaning; allowing ‘override’ to be satisfied by a protocol requirement means that it might miss an override intended for a superclass—or inadvertently become one when an SDK is updated.

(Counter-argument: that last can happen to protocols already.)

- This doesn’t cover cases where methods in one protocol extension satisfy requirements in another.

- This doesn’t cover retroactive modeling.

- I’m not sure what it means to "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)”. Protocol conformance is decided at compile time; there won’t ever be any members in type extensions that take precedent over a type declaration without causing a conflict. (That is, currently you are not allowed to define such a member.)

- A member in the type does not “override" a member in a protocol extension today, because such a call is not dynamically dispatched. Making protocol extension members dynamically dispatched is challenging at the least and would require an implementation plan in the proposal.

- Thank you for writing up all of the source compatibility cases! I think there’s no issue with binary compatibility, since IIUC the proposal doesn’t change how anything is implemented, and we think we know how to handle binary compatibility there. But I’d like to think about it a little more.

- The “A.foo(self)()” syntax is clever, but it doesn’t work correctly for mutating methods (because you can’t curry an inout). On the other hand, JoeG already brought up the idea of making ‘self’ the first argument of the implicit static member. It still doesn’t solve the problem of picking a protocol extension, but that’s not new. (This isn’t a complaint, I guess, just a note.)

I’m not sure I have a meaningful summary or conclusion, but I’d be hesitant to do all of this without these concerns being addressed.

Jordan

It is a good idea to explicitly document the behaviour that this
requirement for override is a compile time check only and does not mean
that already compiled code has to be recompiled to allow a protocol to be
retroactively fitted to an already compiled type.

···

On Friday, 29 April 2016, Matthew Johnson via swift-evolution < swift-evolution@swift.org> wrote:

Sent from my iPad

On Apr 28, 2016, at 5:49 PM, Erica Sadun <erica@ericasadun.com > <javascript:_e(%7B%7D,'cvml','erica@ericasadun.com');>> wrote:

On Apr 28, 2016, at 12:18 PM, Matthew Johnson <matthew@anandabits.com > <javascript:_e(%7B%7D,'cvml','matthew@anandabits.com');>> wrote:
We can't add the keywords if the structs are defined in a module we import
but don't own. We are only declaring the conformance retroactively. The
ability to do this is a crucial aspect of generic programming. It isn't
yet clear how your proposal handles retroactive modeling.

These are compile-time checks and should not affect compiled code.

Does that mean the conformance declaration will be accepted by the
compiler under your proposal? I would really like to see this called out
explicitly in the proposal.

-- E

--
-- Howard.

The pitch was not warmly received. If you want to pick it up and run with it, go ahead.

I have a running list of dead or deferred ideas here: AltTOC.md · GitHub

-- E

···

On May 9, 2016, at 11:49 AM, Vladimir.S <svabox@gmail.com> wrote:

Hi Erica, could you clarify, what is state of this proposal and your plans regarding it? I believe we certainly should make Swift more explicit regarding what methods in type are required by the conformed protocol and what methods are required(and which are 'optional') in protocol extensions.

Right now there is a discussion regarding 'optional' keyword("Modify optional method semantics for swift"), and I remembered your proposal..

Probably 'optional' keyword for non-required methods in extension instead of marking 'required' methods will looks better(as they are optional to the protocol itself), what do you think?
I.e.

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..

   func blort() {} // Correct, was introduced in `A`
   optional func womble() {} // Correct, new(optional) method in extension
   optional func gar() {} // Incorrect: Compiler says: remove `optional`..
}

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

   func womble() {} // ?? how this method should be 'marked' ??
}

(But personally I think one *overload* keyword will do the job in both cases - in extension and in type declaration)

Regarding this "func womble()" questions.. I think we need *at least* compilation warning that *at the moment of compilation*, B.womble may(?) conflicts with extension of A.womble.

Personaly I was not expecting to get the result of this code:

protocol A {
func a()
}

extension A {
  func b() { print("(b) in A") }
}

struct C : A {
   func a() {}
   func b() { print("(b) in C") }
}

var c : A = C()
c.b() // (b) in A

On 28.04.2016 19:53, Erica Sadun via swift-evolution 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&gt;
* Status: tbd
* Review manager: tbd2

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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&gt; thread/

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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.
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   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 |override|keyword.

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   Considered

Not at this time.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   and Thanks

Thanks, Doug Gregor, Jordan Rose, and Joe Groff

On Apr 27, 2016, at 6:07 PM, Douglas Gregor <dgregor@apple.com >>>> <mailto:dgregor@apple.com>> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I'm thinking about this.. but first, could someone *please* describe(clarify) the behavior of the next code and if that behavior is expected and if we really need exactly this behavior and if we can(I mean if it is not too hard) change this.. :

protocol A {
}

extension A {
     func a() { print("(a) in extension of A") }

     static func b() {print("(static b) in extension of A")}
}

struct S : A {
     func a() { print("(a) in S") }

     static func b() {print("(static b) in S")}
}

var s : A = S()

print("s.dynamicType = ", s.dynamicType)
s.a()
s.dynamicType.b()

Result is :

s.dynamicType = S
(a) in extension of A
(static b) in extension of A

IMO This is definitely not the "less surprising" behavior.
Thank you.

···

On 09.05.2016 21:03, Erica Sadun wrote:

The pitch was not warmly received. If you want to pick it up and run with
it, go ahead.
Requiring Proactive Overrides for Default Protocol Implementations · GitHub

I have a running list of dead or deferred ideas
here: AltTOC.md · GitHub

-- E

On May 9, 2016, at 11:49 AM, Vladimir.S <svabox@gmail.com >> <mailto:svabox@gmail.com>> wrote:

Hi Erica, could you clarify, what is state of this proposal and your
plans regarding it? I believe we certainly should make Swift more
explicit regarding what methods in type are required by the conformed
protocol and what methods are required(and which are 'optional') in
protocol extensions.

Right now there is a discussion regarding 'optional' keyword("Modify
optional method semantics for swift"), and I remembered your proposal..

Probably 'optional' keyword for non-required methods in extension instead
of marking 'required' methods will looks better(as they are optional to
the protocol itself), what do you think?
I.e.

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..

   func blort() {} // Correct, was introduced in `A`
   optional func womble() {} // Correct, new(optional) method in extension
   optional func gar() {} // Incorrect: Compiler says: remove `optional`..
}

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

   func womble() {} // ?? how this method should be 'marked' ??
}

(But personally I think one *overload* keyword will do the job in both
cases - in extension and in type declaration)

Regarding this "func womble()" questions.. I think we need *at least*
compilation warning that *at the moment of compilation*, B.womble may(?)
conflicts with extension of A.womble.

Personaly I was not expecting to get the result of this code:

protocol A {
func a()
}

extension A {
  func b() { print("(b) in A") }
}

struct C : A {
   func a() {}
   func b() { print("(b) in C") }
}

var c : A = C()
c.b() // (b) in A

On 28.04.2016 19:53, Erica Sadun via swift-evolution 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&gt;
* Status: tbd
* Review manager: tbd2

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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&gt; thread/

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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.
}

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

       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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   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 |override|keyword.

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.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   Considered

Not at this time.

<Requiring Proactive Overrides for Default Protocol Implementations · GitHub

   and Thanks

Thanks, Doug Gregor, Jordan Rose, and Joe Groff

On Apr 27, 2016, at 6:07 PM, Douglas Gregor <dgregor@apple.com >>>>> <mailto:dgregor@apple.com> >>>>> <mailto:dgregor@apple.com>> wrote:

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

At this time, default protocol implementations do not exist.

At compilation time, either a protocol default exists or it does not. The goal of this proposal is to increase safety through syntax.

What is the current behavior where a subclass is pre-compiled and the superclass then changes through an extension to implement a member that the already compiled subclass had implemented but not as an override?

-- E

···

On Apr 28, 2016, at 5:09 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

It is a good idea to explicitly document the behaviour that this requirement for override is a compile time check only and does not mean that already compiled code has to be recompiled to allow a protocol to be retroactively fitted to an already compiled type.

I'm making live updates at the gist in response to on-list discussions:

If you have specific suggestions for modifications, I'll be happy to evaluate for incorporation.

-- E

···

On Friday, 29 April 2016, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Does that mean the conformance declaration will be accepted by the compiler under your proposal? I would really like to see this called out explicitly in the proposal.

Can you give me a specific example of where this approach fails for you?

-- E

···

On Apr 28, 2016, at 5:24 PM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

I'm not sure that I'm entirely happy with this distinction between already compiled types and ones that have not yet been compiled. It's a common Swift idiom to implement protocol requirements in extensions, which encourages a kind of modularity, if you will. Every so often (and maybe this isn't best practice), I incorporate third-party code into a project in source form and not as a compiled library (with attribution, and in compliance with the license, etc., obviously). Often these are little snippets, perhaps useful helper functions or types. The beauty of extensions is that I can extend these as necessary without touching the original code. The point is, here one would not be able to implement certain things in that way if this proposal is adopted. To say that the workaround is just editing the original code is deeply unsatisfying, because it would be equally valid to say that the same workaround applies to stripping out extensions altogether for non-imported types.

On Thu, Apr 28, 2016 at 6:09 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
It is a good idea to explicitly document the behaviour that this requirement for override is a compile time check only and does not mean that already compiled code has to be recompiled to allow a protocol to be retroactively fitted to an already compiled type.

On Friday, 29 April 2016, Matthew Johnson via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sent from my iPad

On Apr 28, 2016, at 5:49 PM, Erica Sadun <erica@ericasadun.com <>> wrote:

On Apr 28, 2016, at 12:18 PM, Matthew Johnson <matthew@anandabits.com <>> wrote:
We can't add the keywords if the structs are defined in a module we import but don't own. We are only declaring the conformance retroactively. The ability to do this is a crucial aspect of generic programming. It isn't yet clear how your proposal handles retroactive modeling.

These are compile-time checks and should not affect compiled code.

Does that mean the conformance declaration will be accepted by the compiler under your proposal? I would really like to see this called out explicitly in the proposal.

-- E

--
-- Howard.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

I'm not sure that I'm entirely happy with this distinction between already
compiled types and ones that have not yet been compiled. It's a common
Swift idiom to implement protocol requirements in extensions, which
encourages a kind of modularity, if you will. Every so often (and maybe
this isn't best practice), I incorporate third-party code into a project in
source form and not as a compiled library (with attribution, and in
compliance with the license, etc., obviously). Often these are little
snippets, perhaps useful helper functions or types. The beauty of
extensions is that I can extend these as necessary without touching the
original code. The point is, here one would not be able to implement
certain things in that way if this proposal is adopted. To say that the
workaround is just editing the original code is deeply unsatisfying,
because it would be equally valid to say that the same workaround applies
to stripping out extensions altogether for non-imported types.

···

On Thu, Apr 28, 2016 at 6:09 PM, Howard Lovatt via swift-evolution < swift-evolution@swift.org> wrote:

It is a good idea to explicitly document the behaviour that this
requirement for override is a compile time check only and does not mean
that already compiled code has to be recompiled to allow a protocol to be
retroactively fitted to an already compiled type.

On Friday, 29 April 2016, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

Sent from my iPad

On Apr 28, 2016, at 5:49 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 28, 2016, at 12:18 PM, Matthew Johnson <matthew@anandabits.com> >> wrote:
We can't add the keywords if the structs are defined in a module we
import but don't own. We are only declaring the conformance
retroactively. The ability to do this is a crucial aspect of generic
programming. It isn't yet clear how your proposal handles retroactive
modeling.

These are compile-time checks and should not affect compiled code.

Does that mean the conformance declaration will be accepted by the
compiler under your proposal? I would really like to see this called out
explicitly in the proposal.

-- E

--
-- Howard.

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Why allow both `override` and `required`? I understand you mean it to
indicate that you're overriding a requirement, but does that provide any
additional safety? Both say "I intend to name something the same as
something else."

In addition, the juxtaposition of both keywords can be misunderstood.
Specifically: required suggests that something not otherwise there must be
there. Override suggests that there's already something there. The act of
overriding can never itself be "required." It's could be thought of as an
oxymoron to have both, no?

···

On Thu, Apr 28, 2016 at 6:20 PM, Erica Sadun via swift-evolution < swift-evolution@swift.org> wrote:

On Friday, 29 April 2016, Matthew Johnson via swift-evolution < > swift-evolution@swift.org> wrote:

Does that mean the conformance declaration will be accepted by the
compiler under your proposal? I would really like to see this called out
explicitly in the proposal.

I'm making live updates at the gist in response to on-list discussions:

Requiring Proactive Overrides for Default Protocol Implementations · GitHub

If you have specific suggestions for modifications, I'll be happy to
evaluate for incorporation.

-- E

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Does that mean the conformance declaration will be accepted by the compiler under your proposal? I would really like to see this called out explicitly in the proposal.

I'm making live updates at the gist in response to on-list discussions:

Requiring Proactive Overrides for Default Protocol Implementations · GitHub

If you have specific suggestions for modifications, I'll be happy to evaluate for incorporation.

Unfortunately I don't have specific suggestions as there are flaws with all of the approaches I can think of. However, I do think *something* needs to be specified regarding behavior when retroactively conforming a type from a different module which doesn't know anything about the protocol but does implement the requirements (as normal methods). I can't determine how I feel about this proposal without seeing it clearly specified.

···

Sent from my iPad

On Apr 28, 2016, at 6:20 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Friday, 29 April 2016, Matthew Johnson via swift-evolution <swift-evolution@swift.org> wrote:

-- E

Can you give me a specific example of where this approach fails for you?

-- E

Sure, I'll describe one (renaming some things for clarity and stripping out
the meat of the code, because it's not relevant and because it's not
elegant)--

In one file, I have:

class PortedTransfom {
// this class was ported from C++
// it transforms input FP values to output values in a complicated way
// it's a standalone entity and the algorithm is even under patent
// (not owned by me, though it's legal for me to use it for my purposes)
// for this reason, this ported code lives in its own file
}

In another file, I have:

class MyAsinhTransform {
// this class was written by me
// nothing earth-shattering here
}

class MyLogTransform {
// also written by me
}

class MyLinearTransform {
// also written by me
}

Transforming values one-at-a-time isn't fast enough, so in another file, I
have:

import Accelerate

protocol AcceleratedTransform {
  func scale(_: [Double]) -> [Double]
  func unscale(_: [Double]) -> [Double]
// other functions here
// some are already implemented in PortedTransform, though
}
extension AcceleratedTransform {
// default implementations for some functions
// but not `scale(_:)` and `unscale(_:)`, obviously
}

extension MyAsinhTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension MyLogTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension  MyLinearTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension PortedTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
}
···

On Thu, Apr 28, 2016 at 6:44 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 28, 2016, at 5:24 PM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

I'm not sure that I'm entirely happy with this distinction between already
compiled types and ones that have not yet been compiled. It's a common
Swift idiom to implement protocol requirements in extensions, which
encourages a kind of modularity, if you will. Every so often (and maybe
this isn't best practice), I incorporate third-party code into a project in
source form and not as a compiled library (with attribution, and in
compliance with the license, etc., obviously). Often these are little
snippets, perhaps useful helper functions or types. The beauty of
extensions is that I can extend these as necessary without touching the
original code. The point is, here one would not be able to implement
certain things in that way if this proposal is adopted. To say that the
workaround is just editing the original code is deeply unsatisfying,
because it would be equally valid to say that the same workaround applies
to stripping out extensions altogether for non-imported types.

On Thu, Apr 28, 2016 at 6:09 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

It is a good idea to explicitly document the behaviour that this
requirement for override is a compile time check only and does not mean
that already compiled code has to be recompiled to allow a protocol to be
retroactively fitted to an already compiled type.

On Friday, 29 April 2016, Matthew Johnson via swift-evolution < >> swift-evolution@swift.org> wrote:

Sent from my iPad

On Apr 28, 2016, at 5:49 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 28, 2016, at 12:18 PM, Matthew Johnson <matthew@anandabits.com> >>> wrote:
We can't add the keywords if the structs are defined in a module we
import but don't own. We are only declaring the conformance
retroactively. The ability to do this is a crucial aspect of generic
programming. It isn't yet clear how your proposal handles retroactive
modeling.

These are compile-time checks and should not affect compiled code.

Does that mean the conformance declaration will be accepted by the
compiler under your proposal? I would really like to see this called out
explicitly in the proposal.

-- E

--
-- Howard.

_______________________________________________
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

I think I'm missing something here in terms of a question. Your imported stuff is your imported stuff.
Your extension implements "required" elements but not scale or unscale.

If you extend MyAsinhTransform, you do required but not override for scale/unscale. You do required override for anything you replace from AcceleratedTransform.
What is BLAS? And what are you specifically asking about?

-- E, apologizing for not understanding

···

On Apr 28, 2016, at 6:20 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Apr 28, 2016 at 6:44 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:
Can you give me a specific example of where this approach fails for you?

-- E

Sure, I'll describe one (renaming some things for clarity and stripping out the meat of the code, because it's not relevant and because it's not elegant)--

In one file, I have:

class PortedTransfom {
// this class was ported from C++
// it transforms input FP values to output values in a complicated way
// it's a standalone entity and the algorithm is even under patent
// (not owned by me, though it's legal for me to use it for my purposes)
// for this reason, this ported code lives in its own file
}

In another file, I have:

class MyAsinhTransform {
// this class was written by me
// nothing earth-shattering here
}

class MyLogTransform {
// also written by me
}

class MyLinearTransform {
// also written by me
}

Transforming values one-at-a-time isn't fast enough, so in another file, I have:

import Accelerate

protocol AcceleratedTransform {
  func scale(_: [Double]) -> [Double]
  func unscale(_: [Double]) -> [Double]
// other functions here
// some are already implemented in PortedTransform, though
}
extension AcceleratedTransform {
// default implementations for some functions
// but not `scale(_:)` and `unscale(_:)`, obviously
}

extension MyAsinhTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension MyLogTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension  MyLinearTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension PortedTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
}

Without actually trying to understand the details of your math stuff:

* If you add a required member in a declaration or extension that declares conformance, it is 'required'.
* If it is already defaulted, it is `override required`.
* If it is already defaulted but not required, it is `override`
* If someone else implements the stuff, you still have to pull it in somehow, but if you do so by conforming to another protocol with an extension, it's not your business, so you don't use any keywords.

You use keywords only for stuff that you specifically write, that clarifies the context in which you are writing it. If you do not own a protocol, an extension, or an implementation, you do not change or markup the protocol, extension, or implementation. You're just offering the compiler hints that your otherwise questionable decisions are fully intentional: when overriding an existing implementation and when conforming by supplying a required member.

-- E, who still probably missed your point and again apologizes

···

On Apr 28, 2016, at 8:11 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Sorry, stripped out a little too much, I guess. Let me expand a little:

In this example, `PortedTransform` has, by virtue of how it works, an upper bound and lower bound for valid input (among other interesting methods and properties). Exceed those bounds for your input and `PortedTransform` regurgitates garbage but does not throw any kind of error. Obviously, linear transform does not care about such silly things because it can transform essentially any FP input value, while the log transform simply traps when it encounters a negative value (which, as a precondition, it should never encounter).

BLAS is an accelerated linear algebra library; Apple has implemented a very nicely optimized one as part of its Accelerate framework. I use BLAS to sum, for example, two arrays of floating point values--it's very, very highly optimized. In that situation, there's no trapping when a single value is out of bounds (I get NaNs instead), and thus I must determine bounds in order to anticipate when the output will be garbage or NaN. (There are, as part of the Accelerate framework, accelerated functions to clamp entire arrays to given bounds with maximal efficiency).

For accelerated scaling and unscaling, then, it is essentially always necessary to compute upper and lower bounds even when that's unnecessary for non-accelerated scaling and unscaling, which operates on one value at a time. For that reason, `AcceleratedTransform` requires methods that compute upper and lower bounds, and provides a default implementation of accelerated clamping that calls those bound-computing methods and then uses the results as parameters when calling functions in Accelerate.framework. Methods for the computation of bounds already exist in `PortedTransform` but not in my own transforms. With your proposal, how would I retroactively model this requirement without touching code for `PortedTransform` and without compiling this one class into its own library? I'd like to be able to take advantage of the maximum possible compiler optimization, and optimizing across module boundaries is (as far as I understand) a little dicier. (Moreover, for MyLinTransform, I override the clamping method to return the input without calling out to any framework functions because I know a priori that the bounds are -infinity and infinity. I think that override will still be possible under your proposal, though.)

* If this is not Swift code it is not affected.
* If it is Swift code, either use if swift(>= blah) workarounds or propose that SwiftPM support earlier Swift compilation rules.
* If this is adopted and the code is in Swift 3, it would already have compliances and you do not need to add anything

Under what scenario could you possibly use 3rd party Swift 3 code (assuming adoption) that would require annotation/changing?

-- Erica

···

On Apr 28, 2016, at 8:25 PM, Erica Sadun via swift-evolution <swift-evolution@swift.org> wrote:

On Apr 28, 2016, at 8:11 PM, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

Sorry, stripped out a little too much, I guess. Let me expand a little:

In this example, `PortedTransform` has, by virtue of how it works, an upper bound and lower bound for valid input (among other interesting methods and properties). Exceed those bounds for your input and `PortedTransform` regurgitates garbage but does not throw any kind of error. Obviously, linear transform does not care about such silly things because it can transform essentially any FP input value, while the log transform simply traps when it encounters a negative value (which, as a precondition, it should never encounter).

BLAS is an accelerated linear algebra library; Apple has implemented a very nicely optimized one as part of its Accelerate framework. I use BLAS to sum, for example, two arrays of floating point values--it's very, very highly optimized. In that situation, there's no trapping when a single value is out of bounds (I get NaNs instead), and thus I must determine bounds in order to anticipate when the output will be garbage or NaN. (There are, as part of the Accelerate framework, accelerated functions to clamp entire arrays to given bounds with maximal efficiency).

For accelerated scaling and unscaling, then, it is essentially always necessary to compute upper and lower bounds even when that's unnecessary for non-accelerated scaling and unscaling, which operates on one value at a time. For that reason, `AcceleratedTransform` requires methods that compute upper and lower bounds, and provides a default implementation of accelerated clamping that calls those bound-computing methods and then uses the results as parameters when calling functions in Accelerate.framework. Methods for the computation of bounds already exist in `PortedTransform` but not in my own transforms. With your proposal, how would I retroactively model this requirement without touching code for `PortedTransform` and without compiling this one class into its own library? I'd like to be able to take advantage of the maximum possible compiler optimization, and optimizing across module boundaries is (as far as I understand) a little dicier. (Moreover, for MyLinTransform, I override the clamping method to return the input without calling out to any framework functions because I know a priori that the bounds are -infinity and infinity. I think that override will still be possible under your proposal, though.)

Without actually trying to understand the details of your math stuff:

* If you add a required member in a declaration or extension that declares conformance, it is 'required'.
* If it is already defaulted, it is `override required`.
* If it is already defaulted but not required, it is `override`
* If someone else implements the stuff, you still have to pull it in somehow, but if you do so by conforming to another protocol with an extension, it's not your business, so you don't use any keywords.

You use keywords only for stuff that you specifically write, that clarifies the context in which you are writing it. If you do not own a protocol, an extension, or an implementation, you do not change or markup the protocol, extension, or implementation. You're just offering the compiler hints that your otherwise questionable decisions are fully intentional: when overriding an existing implementation and when conforming by supplying a required member.

-- E, who still probably missed your point and again apologizes

Is this your desired behavior or is this the behavior you expect?
By implementing a default, you inherit that behavior in all three, because *you* added it.
I expect the compiler to complain at your default because you did not mark it as required.

If you want to use the inherent frobnicate and not the default one that you just added,
you will need to do something like:

extension A: Frobnicate {
   override required frobnicate = A.frobnicate
}

-- E

···

On Apr 28, 2016, at 8:46 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:
Let's return to the toy example. Suppose I license the following code from a third party. I am allowed to incorporate it unmodified into my project:

// I cannot touch any of the following code
struct A {
    func frobnicate() { print("A") }
}
struct B {
    func frobnicate() { print("B") }
}
struct C { }

The code above has three types that conform to no protocols. Nothing would change on adoption of your proposal. As licensed to me from the third party, there are no protocols for it to conform to.

Now, in a separate file, as part of my own code, I want to conform these three types to a protocol of my own design, Frobnicatable, and supply a default `frobnicate()`:

protocol Frobnicatable {
    func frobnicate()
}
extension Frobnicatable {
    func frobnicate() { print("Default") }
}
extension A: Frobnicatable { }
extension B: Frobnicatable { }
extension C: Frobnicatable { }

let a = A()
a.frobnicate() // "A"
let c = C()
c.frobnicate() // "Default"

It seems like there is nothing I can do to make this work upon implementation of your proposal.

Sorry, stripped out a little too much, I guess. Let me expand a little:

In this example, `PortedTransform` has, by virtue of how it works, an upper
bound and lower bound for valid input (among other interesting methods and
properties). Exceed those bounds for your input and `PortedTransform`
regurgitates garbage but does not throw any kind of error. Obviously,
linear transform does not care about such silly things because it can
transform essentially any FP input value, while the log transform simply
traps when it encounters a negative value (which, as a precondition, it
should never encounter).

BLAS is an accelerated linear algebra library; Apple has implemented a very
nicely optimized one as part of its Accelerate framework. I use BLAS to
sum, for example, two arrays of floating point values--it's very, very
highly optimized. In that situation, there's no trapping when a single
value is out of bounds (I get NaNs instead), and thus I must determine
bounds in order to anticipate when the output will be garbage or NaN.
(There are, as part of the Accelerate framework, accelerated functions to
clamp entire arrays to given bounds with maximal efficiency).

For accelerated scaling and unscaling, then, it is essentially always
necessary to compute upper and lower bounds even when that's unnecessary
for non-accelerated scaling and unscaling, which operates on one value at a
time. For that reason, `AcceleratedTransform` requires methods that compute
upper and lower bounds, and provides a default implementation of
accelerated clamping that calls those bound-computing methods and then uses
the results as parameters when calling functions in Accelerate.framework.
Methods for the computation of bounds already exist in `PortedTransform`
but not in my own transforms. With your proposal, how would I retroactively
model this requirement without touching code for `PortedTransform` and
without compiling this one class into its own library? I'd like to be able
to take advantage of the maximum possible compiler optimization, and
optimizing across module boundaries is (as far as I understand) a little
dicier. (Moreover, for MyLinTransform, I override the clamping method to
return the input without calling out to any framework functions because I
know a priori that the bounds are -infinity and infinity. I think that
override will still be possible under your proposal, though.)

···

On Thu, Apr 28, 2016 at 8:32 PM, Erica Sadun <erica@ericasadun.com> wrote:

On Apr 28, 2016, at 6:20 PM, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Thu, Apr 28, 2016 at 6:44 PM, Erica Sadun <erica@ericasadun.com> wrote:

Can you give me a specific example of where this approach fails for you?

-- E

Sure, I'll describe one (renaming some things for clarity and stripping
out the meat of the code, because it's not relevant and because it's not
elegant)--

In one file, I have:

class PortedTransfom {
// this class was ported from C++
// it transforms input FP values to output values in a complicated way
// it's a standalone entity and the algorithm is even under patent
// (not owned by me, though it's legal for me to use it for my purposes)
// for this reason, this ported code lives in its own file
}

In another file, I have:

class MyAsinhTransform {
// this class was written by me
// nothing earth-shattering here
}

class MyLogTransform {
// also written by me
}

class MyLinearTransform {
// also written by me
}

Transforming values one-at-a-time isn't fast enough, so in another file, I
have:

import Accelerate

protocol AcceleratedTransform {
  func scale(_: [Double]) -> [Double]
  func unscale(_: [Double]) -> [Double]
// other functions here
// some are already implemented in PortedTransform, though
}
extension AcceleratedTransform {
// default implementations for some functions
// but not `scale(_:)` and `unscale(_:)`, obviously
}

extension MyAsinhTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension MyLogTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension  MyLinearTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
// and override some default implementations
}

extension PortedTransform : AcceleratedTransform {
// use BLAS to implement scale(_:) and unscale(_:)
}

I think I'm missing something here in terms of a question. Your imported
stuff is your imported stuff.
Your extension implements "required" elements but not scale or unscale.

If you extend MyAsinhTransform, you do required but not override for
scale/unscale. You do required override for anything you replace from
AcceleratedTransform.
What is BLAS? And what are you specifically asking about?

-- E, apologizing for not understanding