[Pitch] Requiring special keyword to mark protocol implementation methods


(Vladimir) #1

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3 as we can reasonably accomplish". Or this can be discussed as 'after Swift 3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type specifically to fulfill a protocol requirements. And so we will have more understandable and self-documented code that is explicit regarding the fact of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential problems/error/misunderstanding in case some protocol requirement(method) were *removed* - in this case (currently) our type will still have a method as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type) that were defined in order to conform to protocol.
Also, *reimplement* keyword is proposed to reflect the fact that method is declared in *both* : in the type and in protocol extension (only in extension, no definition of the method in protocol itself)

Rules

* Each method in type defined to fulfill the protocol conformance should be marked with `implement` keyword:
implement func protocolRequirement() {..}

* Compiler produces *warning* if the same function is declared in type and in protocol extension in case class conformed to that protocol. To 'fix' the warning, `reimplement` should be used.
reimplement func f() {..} // we aware that the same method in protocol extension

* don't need to mark methods for type if conformance to protocol defined by separate type extension

* `reimplement` can be placed in defining type or as special declaration in type extension anywhere in source code:
extension Type {
   reimplement methodDeclaredInBothTypeAndInProtocolExtension(..); // no body here. probably `;` is required - to be discussed
}
(I don't really like this requirement, but right now don't know if we can do the same by using any other method )

Current behavior of protocol extension

When method is declared in protocol extension(*only. no in protocol itself*) and in type that is conformed to the protocol, there is a possibility for confusion about which method will be called. Example:

protocol A { func a() }
extension A { func b() {print("Hello from b() in extension A")} }

class B : A {
     func a() {}
     func b() {print("Hello from b() in B")}
}

let instance1 = B()
instance1.b() // Hello from b() in B

let instance2 : A = B()
instance2.b() // Hello from b() in extension A

func f<T:A>(t: T) { t.b() }
f(instance1) // Hello from b() in extension A

In this proposal I suggest compiler will generate a *warning* in this case(not error). This warning can be fixed with `reimplement` keyword for b() in class B.

`Override` keyword alternative

I think that `override` keyword can not be used instead of new `implement`, as the first clearly means now that method overrides one of the methods from base class. Such method already has implementation in base class(in compare with protocol requirement) and 'belongs' to `class` not to `protocol`. So, in case of `override` keyword for protocol implementation we'll have questions if super.method() should be called inside.
Also, usually declaration of `override` method is not required, in opposite to implementation of protocol requirement.

Questions to discuss

* Should `reimplement` be used only when exactly the same method declared(arguments+return type the same) or even if just method name is the same(in extension there is f(v: Float) in type f(v:Double)) ? I'd prefer the second, but I don't feel this will be supported by community.

Code Examples:

A) ------------------------------------------------

1. We have some protocol:

protocol A {
     func a()
     func b()
     func c()
}

2. Then extension is defined for it:

extension A {
     implement func a() {} // Correct, `a` was declared in `A`

     //func b() {}
     // Incorrect: `b` was declared in `A`, `implement` is required
     // Compiler says: add `implement` keyword or remove implementation

     func d() {} // Correct, new method in extension

     //implement func e() {}
     // Incorrect: `e` was not declared in `A`, `implement` should be removed
     // Compiler says: remove `implement` keyword or remove implementation
}

3. *We* are writting the type S that conforms to A protocol:

struct S: A {
     implement func a() {} // Correct. We implemented A's requirement

     //func b() {}
     // Incorrect: add `implement` keyword or rename the method

     implement func b() {} // Correct
     implement func c() {} // Correct

     //implement func f() {}
     // Incorrect: No `f` declaration in protocol. Compiler: rename method or drop `implement` keyword

     //func d() {}
     // Incorrect: Possible accidental name match.
     // Compiler: rename method or add `reimplement` keyword

     reimplement func d() {} // Correct. We are explicit about the fact that our type has the same function as in extension of conformed protocol
}

B) ------------------------------------------------

1. Having declared protocol:

protocol A {
     func a()
     func b()
     func c()
}

2. Have defined extension

extension A {
     implement func a() {} // Correct, `a` was declared in `A`

     //func b() {}
     // Incorrect: `b` was declared in `A`, `implement` is required
     // Compiler says: add `implement` keyword or remove implementation

     func d() {} // Correct, new method in extension

     //implement func e() {}
     // Incorrect: `e` was not declared in `A`, `implement` should be removed
     // Compiler says: remove `implement` keyword or remove implementation
}

3. Have a type that we can't/don't want to change

struct S { // at this moment S don't care about any protocol
     func a() {}
     func b() {}
     func c() {}
     func d() {}
}

4. *We* need (for some task) to conform the S type to protocol A in our own code. So we do:

extension S : A {
     // no need of any special steps for a(), b(), c()
     // as we just said "we sure S conforms to A"

     // but we need to care about special case - d() method, which is defined in S type and in extension of A protocol
     reimplement d(); // probably `;` is required here
}

C) ------------------------------------------------

1. Have protocol

protocol A {
     func a()
     func b()
     func c()
}

2. Have a Type

struct S { // at this moment S don't care about any protocol
     func a() {}
     func b() {}
     func c() {}
     func d() {}
}

3. Conforms to protocol

extension S : A {
     // no need of any special steps for a(), b(), c()
     // as we just said "we sure S conforms to A"
     // here(at the moment of *writing*) S don't know about any extension of A
}

4. Now protocol extension is defined:

extension A {
     implement func a() {} // Correct, `a` was declared in `A`

     //func b() {}
     // Incorrect: `b` was declared in `A`, `implement` is required
     // Compiler says: add `implement` keyword or remove implementation

     func d() {} // Correct, new method in extension
}

5. But now we have a problem : same d() method in S and in A extension
Compiler will raise a warning : Possible accidental name match of d() in S, also defined in extension of A. Change method name or add `reimplement` keyword

In case we can't or don't want to change the method name(in type or in protocol) - the only solution is to say "it's OK" to the compiler anywhere in our code:

extension S {
     reimplement d(); // notify the compiler that we are aware of the same names
}

Thank you for your opinions on this.


(Leonardo Pessoa) #2

Hi Vladmir!

There is something very similar to this in C#. I like this but I'd
like to enhance it a little bit. I don't think it's necessary to
decorate protocol methods any further but some warnings by the
compiler would be welcome, like when pushing a type to adopt a
protocol through an extension when the type already implements a
protocol method (we should need an annotation to tell the compiler we
understand this). This would be my version of the proposal:

    protocol IX {
       func somethingA()
       func somethingB()
    }

    class X {
       func somethingA() { ... }
    }

    @warn_implemented(IX.somethingA) // any better ideas?
    extension X : IX {
       func something() implements IX.somethingB { ... }
    }

My issue here is: what if I need to adopt two protocols (from
different vendors, I suppose) which require the same method and
signature but for each interface you're expected to have a different
outcome? I think better than just saying a method is an implementation
required by a protocol is to say explicitly which protocol required
that implementation. I'd also suggest a syntax for declaring a method
that is not visible but through a cast to the protocol if that makes
any sense to you.

A method implementation can have a different name if you remember two
different protocols could use the same name and signature; a new name
would disambiguate them to us, the implements part would disambiguate
for the compiler.

What do you think?

···

On 18 May 2016 at 04:28, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this
proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3
as we can reasonably accomplish". Or this can be discussed as 'after Swift
3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type
specifically to fulfill a protocol requirements. And so we will have more
understandable and self-documented code that is explicit regarding the fact
of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential
problems/error/misunderstanding in case some protocol requirement(method)
were *removed* - in this case (currently) our type will still have a method
as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type)
that were defined in order to conform to protocol.
Also, *reimplement* keyword is proposed to reflect the fact that method is
declared in *both* : in the type and in protocol extension (only in
extension, no definition of the method in protocol itself)

Rules

* Each method in type defined to fulfill the protocol conformance should be
marked with `implement` keyword:
implement func protocolRequirement() {..}

* Compiler produces *warning* if the same function is declared in type and
in protocol extension in case class conformed to that protocol. To 'fix' the
warning, `reimplement` should be used.
reimplement func f() {..} // we aware that the same method in protocol
extension

* don't need to mark methods for type if conformance to protocol defined by
separate type extension

* `reimplement` can be placed in defining type or as special declaration in
type extension anywhere in source code:
extension Type {
  reimplement methodDeclaredInBothTypeAndInProtocolExtension(..); // no body
here. probably `;` is required - to be discussed
}
(I don't really like this requirement, but right now don't know if we can do
the same by using any other method )

Current behavior of protocol extension

When method is declared in protocol extension(*only. no in protocol itself*)
and in type that is conformed to the protocol, there is a possibility for
confusion about which method will be called. Example:

protocol A { func a() }
extension A { func b() {print("Hello from b() in extension A")} }

class B : A {
    func a() {}
    func b() {print("Hello from b() in B")}
}

let instance1 = B()
instance1.b() // Hello from b() in B

let instance2 : A = B()
instance2.b() // Hello from b() in extension A

func f<T:A>(t: T) { t.b() }
f(instance1) // Hello from b() in extension A

In this proposal I suggest compiler will generate a *warning* in this
case(not error). This warning can be fixed with `reimplement` keyword for
b() in class B.

`Override` keyword alternative

I think that `override` keyword can not be used instead of new `implement`,
as the first clearly means now that method overrides one of the methods from
base class. Such method already has implementation in base class(in compare
with protocol requirement) and 'belongs' to `class` not to `protocol`. So,
in case of `override` keyword for protocol implementation we'll have
questions if super.method() should be called inside.
Also, usually declaration of `override` method is not required, in opposite
to implementation of protocol requirement.

Questions to discuss

* Should `reimplement` be used only when exactly the same method
declared(arguments+return type the same) or even if just method name is the
same(in extension there is f(v: Float) in type f(v:Double)) ? I'd prefer the
second, but I don't feel this will be supported by community.

Code Examples:

A) ------------------------------------------------

1. We have some protocol:

protocol A {
    func a()
    func b()
    func c()
}

2. Then extension is defined for it:

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension

    //implement func e() {}
    // Incorrect: `e` was not declared in `A`, `implement` should be removed
    // Compiler says: remove `implement` keyword or remove implementation
}

3. *We* are writting the type S that conforms to A protocol:

struct S: A {
    implement func a() {} // Correct. We implemented A's requirement

    //func b() {}
    // Incorrect: add `implement` keyword or rename the method

    implement func b() {} // Correct
    implement func c() {} // Correct

    //implement func f() {}
    // Incorrect: No `f` declaration in protocol. Compiler: rename method or
drop `implement` keyword

    //func d() {}
    // Incorrect: Possible accidental name match.
    // Compiler: rename method or add `reimplement` keyword

    reimplement func d() {} // Correct. We are explicit about the fact that
our type has the same function as in extension of conformed protocol
}

B) ------------------------------------------------

1. Having declared protocol:

protocol A {
    func a()
    func b()
    func c()
}

2. Have defined extension

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension

    //implement func e() {}
    // Incorrect: `e` was not declared in `A`, `implement` should be removed
    // Compiler says: remove `implement` keyword or remove implementation
}

3. Have a type that we can't/don't want to change

struct S { // at this moment S don't care about any protocol
    func a() {}
    func b() {}
    func c() {}
    func d() {}
}

4. *We* need (for some task) to conform the S type to protocol A in our own
code. So we do:

extension S : A {
    // no need of any special steps for a(), b(), c()
    // as we just said "we sure S conforms to A"

    // but we need to care about special case - d() method, which is defined
in S type and in extension of A protocol
    reimplement d(); // probably `;` is required here
}

C) ------------------------------------------------

1. Have protocol

protocol A {
    func a()
    func b()
    func c()
}

2. Have a Type

struct S { // at this moment S don't care about any protocol
    func a() {}
    func b() {}
    func c() {}
    func d() {}
}

3. Conforms to protocol

extension S : A {
    // no need of any special steps for a(), b(), c()
    // as we just said "we sure S conforms to A"
    // here(at the moment of *writing*) S don't know about any extension of
A
}

4. Now protocol extension is defined:

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension
}

5. But now we have a problem : same d() method in S and in A extension
Compiler will raise a warning : Possible accidental name match of d() in S,
also defined in extension of A. Change method name or add `reimplement`
keyword

In case we can't or don't want to change the method name(in type or in
protocol) - the only solution is to say "it's OK" to the compiler anywhere
in our code:

extension S {
    reimplement d(); // notify the compiler that we are aware of the same
names
}

Thank you for your opinions on this.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Douglas Gregor) #3

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3 as we can reasonably accomplish". Or this can be discussed as 'after Swift 3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type specifically to fulfill a protocol requirements. And so we will have more understandable and self-documented code that is explicit regarding the fact of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential problems/error/misunderstanding in case some protocol requirement(method) were *removed* - in this case (currently) our type will still have a method as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type) that were defined in order to conform to protocol.

I like this better than using the “override” or “required” keywprds.

Also, *reimplement* keyword is proposed to reflect the fact that method is declared in *both* : in the type and in protocol extension (only in extension, no definition of the method in protocol itself)

I (personally) still don’t feel like the cases handled by “reimplement” are important to distinguish from “implement”.

Without digging deeply into your rules, I’d like to reiterate my own (personal!) perspective on why I don’t think we need a keyword here. With a few exceptions, one can freely break up a type’s definition into a number of different extensions. A fairly common style I’ve seen it to use a unique extension for each protocol conformance, because it’s great for readability: this is the functionality that is associated with a particular protocol conformance. This style conveys essentially what the “implements” keyword conveys: that the programmer intends to implement the protocol, but it does so without any extra syntax. Moreover, if we assume that this is good style and widely practiced, the compiler can use it as a cue: non-private declarations that are within an extension that states conformance to P, that are similar to some requirement in P but aren’t used to satisfy any require, are suspicious and should produce a warning.

  - Doug

···

On May 18, 2016, at 12:28 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:


(Vladimir) #4

Leonardo,
Based on the discussion for similar subject, I feel like community and core team does not support the idea of more verbose decoration of protocol implementation in type.
So, my initial proposal is trying to add the minimum of changes to the current state to increase the level of clarity and self-documentation of code, this will help the compiler to help us, plus my proposal can prevent some kind of problems.

As for my initial proposal. Probably the better idea to 'fix' the warning regarding the same name in type and in protocol extension(when there is no such method in protocol itself) will be not
extension S : A { reimplement d(); }
but some kind of
@warn_reimplement(S.d)

You are introducing more verbose decoration, and personally I probably support it, but don't feel like the discussion of it will produce any positive result. So I try to discuss at least this : small decoration of methods that were declared specifically to fulfill the protocol requirements.

···

On 18.05.2016 23:10, Leonardo Pessoa wrote:

Hi Vladmir!

There is something very similar to this in C#. I like this but I'd
like to enhance it a little bit. I don't think it's necessary to
decorate protocol methods any further but some warnings by the
compiler would be welcome, like when pushing a type to adopt a
protocol through an extension when the type already implements a
protocol method (we should need an annotation to tell the compiler we
understand this). This would be my version of the proposal:

    protocol IX {
       func somethingA()
       func somethingB()
    }

    class X {
       func somethingA() { ... }
    }

    @warn_implemented(IX.somethingA) // any better ideas?
    extension X : IX {
       func something() implements IX.somethingB { ... }
    }

My issue here is: what if I need to adopt two protocols (from
different vendors, I suppose) which require the same method and
signature but for each interface you're expected to have a different
outcome? I think better than just saying a method is an implementation
required by a protocol is to say explicitly which protocol required
that implementation. I'd also suggest a syntax for declaring a method
that is not visible but through a cast to the protocol if that makes
any sense to you.

A method implementation can have a different name if you remember two
different protocols could use the same name and signature; a new name
would disambiguate them to us, the implements part would disambiguate
for the compiler.

What do you think?

On 18 May 2016 at 04:28, Vladimir.S via swift-evolution > <swift-evolution@swift.org> wrote:

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this
proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3
as we can reasonably accomplish". Or this can be discussed as 'after Swift
3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type
specifically to fulfill a protocol requirements. And so we will have more
understandable and self-documented code that is explicit regarding the fact
of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential
problems/error/misunderstanding in case some protocol requirement(method)
were *removed* - in this case (currently) our type will still have a method
as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type)
that were defined in order to conform to protocol.
Also, *reimplement* keyword is proposed to reflect the fact that method is
declared in *both* : in the type and in protocol extension (only in
extension, no definition of the method in protocol itself)

Rules

* Each method in type defined to fulfill the protocol conformance should be
marked with `implement` keyword:
implement func protocolRequirement() {..}

* Compiler produces *warning* if the same function is declared in type and
in protocol extension in case class conformed to that protocol. To 'fix' the
warning, `reimplement` should be used.
reimplement func f() {..} // we aware that the same method in protocol
extension

* don't need to mark methods for type if conformance to protocol defined by
separate type extension

* `reimplement` can be placed in defining type or as special declaration in
type extension anywhere in source code:
extension Type {
  reimplement methodDeclaredInBothTypeAndInProtocolExtension(..); // no body
here. probably `;` is required - to be discussed
}
(I don't really like this requirement, but right now don't know if we can do
the same by using any other method )

Current behavior of protocol extension

When method is declared in protocol extension(*only. no in protocol itself*)
and in type that is conformed to the protocol, there is a possibility for
confusion about which method will be called. Example:

protocol A { func a() }
extension A { func b() {print("Hello from b() in extension A")} }

class B : A {
    func a() {}
    func b() {print("Hello from b() in B")}
}

let instance1 = B()
instance1.b() // Hello from b() in B

let instance2 : A = B()
instance2.b() // Hello from b() in extension A

func f<T:A>(t: T) { t.b() }
f(instance1) // Hello from b() in extension A

In this proposal I suggest compiler will generate a *warning* in this
case(not error). This warning can be fixed with `reimplement` keyword for
b() in class B.

`Override` keyword alternative

I think that `override` keyword can not be used instead of new `implement`,
as the first clearly means now that method overrides one of the methods from
base class. Such method already has implementation in base class(in compare
with protocol requirement) and 'belongs' to `class` not to `protocol`. So,
in case of `override` keyword for protocol implementation we'll have
questions if super.method() should be called inside.
Also, usually declaration of `override` method is not required, in opposite
to implementation of protocol requirement.

Questions to discuss

* Should `reimplement` be used only when exactly the same method
declared(arguments+return type the same) or even if just method name is the
same(in extension there is f(v: Float) in type f(v:Double)) ? I'd prefer the
second, but I don't feel this will be supported by community.

Code Examples:

A) ------------------------------------------------

1. We have some protocol:

protocol A {
    func a()
    func b()
    func c()
}

2. Then extension is defined for it:

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension

    //implement func e() {}
    // Incorrect: `e` was not declared in `A`, `implement` should be removed
    // Compiler says: remove `implement` keyword or remove implementation
}

3. *We* are writting the type S that conforms to A protocol:

struct S: A {
    implement func a() {} // Correct. We implemented A's requirement

    //func b() {}
    // Incorrect: add `implement` keyword or rename the method

    implement func b() {} // Correct
    implement func c() {} // Correct

    //implement func f() {}
    // Incorrect: No `f` declaration in protocol. Compiler: rename method or
drop `implement` keyword

    //func d() {}
    // Incorrect: Possible accidental name match.
    // Compiler: rename method or add `reimplement` keyword

    reimplement func d() {} // Correct. We are explicit about the fact that
our type has the same function as in extension of conformed protocol
}

B) ------------------------------------------------

1. Having declared protocol:

protocol A {
    func a()
    func b()
    func c()
}

2. Have defined extension

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension

    //implement func e() {}
    // Incorrect: `e` was not declared in `A`, `implement` should be removed
    // Compiler says: remove `implement` keyword or remove implementation
}

3. Have a type that we can't/don't want to change

struct S { // at this moment S don't care about any protocol
    func a() {}
    func b() {}
    func c() {}
    func d() {}
}

4. *We* need (for some task) to conform the S type to protocol A in our own
code. So we do:

extension S : A {
    // no need of any special steps for a(), b(), c()
    // as we just said "we sure S conforms to A"

    // but we need to care about special case - d() method, which is defined
in S type and in extension of A protocol
    reimplement d(); // probably `;` is required here
}

C) ------------------------------------------------

1. Have protocol

protocol A {
    func a()
    func b()
    func c()
}

2. Have a Type

struct S { // at this moment S don't care about any protocol
    func a() {}
    func b() {}
    func c() {}
    func d() {}
}

3. Conforms to protocol

extension S : A {
    // no need of any special steps for a(), b(), c()
    // as we just said "we sure S conforms to A"
    // here(at the moment of *writing*) S don't know about any extension of
A
}

4. Now protocol extension is defined:

extension A {
    implement func a() {} // Correct, `a` was declared in `A`

    //func b() {}
    // Incorrect: `b` was declared in `A`, `implement` is required
    // Compiler says: add `implement` keyword or remove implementation

    func d() {} // Correct, new method in extension
}

5. But now we have a problem : same d() method in S and in A extension
Compiler will raise a warning : Possible accidental name match of d() in S,
also defined in extension of A. Change method name or add `reimplement`
keyword

In case we can't or don't want to change the method name(in type or in
protocol) - the only solution is to say "it's OK" to the compiler anywhere
in our code:

extension S {
    reimplement d(); // notify the compiler that we are aware of the same
names
}

Thank you for your opinions on this.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(L Mihalkovic) #5

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3 as we can reasonably accomplish". Or this can be discussed as 'after Swift 3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type specifically to fulfill a protocol requirements. And so we will have more understandable and self-documented code that is explicit regarding the fact of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential problems/error/misunderstanding in case some protocol requirement(method) were *removed* - in this case (currently) our type will still have a method as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type) that were defined in order to conform to protocol.

I like this better than using the “override” or “required” keywprds.

Also, *reimplement* keyword is proposed to reflect the fact that method is declared in *both* : in the type and in protocol extension (only in extension, no definition of the method in protocol itself)

I (personally) still don’t feel like the cases handled by “reimplement” are important to distinguish from “implement”.

Without digging deeply into your rules, I’d like to reiterate my own (personal!) perspective on why I don’t think we need a keyword here. With a few exceptions, one can freely break up a type’s definition into a number of different extensions. A fairly common style I’ve seen it to use a unique extension for each protocol conformance, because it’s great for readability: this is the functionality that is associated with a particular protocol conformance. This style conveys essentially what the “implements” keyword conveys: that the programmer intends to implement the protocol, but it does so without any extra syntax. Moreover, if we assume that this is good style and widely practiced, the compiler can use it as a cue: non-private declarations that are within an extension that states conformance to P, that are similar to some requirement in P but aren’t used to satisfy any require, are suspicious and should produce a warning.

Warning on non-private non-conformance yielding methods (helpers) is likely a good thing that would cleanly address some of the issues listed here:

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160516/018560.html

Depending on where things go with protocols, you might still end-up having override creeping its nose, but it could simply be the result of applying current swift rules.

···

On May 23, 2016, at 6:53 AM, Douglas Gregor via swift-evolution <swift-evolution@swift.org> wrote:

On May 18, 2016, at 12:28 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

   - Doug

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


(Vladimir) #6

I (personally) still don’t feel like the cases handled by “reimplement”

are important to distinguish from “implement”.

The main idea was to decorate *type method* that is same as *method in protocol extension* if that method was *not declared in protocol* itself.

So, with very high _possibility_ developer *forgot* (or don't know yet) the rule of static dispatch for such method and *thinks* right now that type's method will be called if type of reference is protocol.

In contrast: implemented methods *declared* in protocol definition, will be(in most cases, yes) dispatched dynamically and so type's methods will be called if reference is a protocol.

Probably 'reimpements' not the best name here, probably 'overload' can be used here.. Or some other to show "Yes, I know this is not the protocol requirement method, I'm aware of its behavior and know that the same method exists in protocol extension only(no in protocol itself)"

>This style conveys essentially what the “implements” keyword conveys: that the programmer intends to implement the protocol, but it does so without any extra syntax.
> Moreover, if we assume that this is good style and widely practiced, the compiler can use it as a cue: non-private declarations that are within an extension that states conformance to P, that are similar to some requirement in P but aren’t used to satisfy any require, are suspicious and should produce a warning.

The idea of proposal is that Swift should help us in situation of protocol conformance:
1. To self-document the code : clearly see which method was implemented specially to fulfill the protocol requirements
2. Raise error/warning if conformed protocol did change: let's consider removed requirement in protocol - with my proposal Swift will flag out that some method decorated with 'implements' didn't declared in protocol. Even important if protocol requirement changed and such requirement has *defailt implmementation* - i.e. without 'implements' keyword, our type, previously implemented all needed methods, will still have them, assuming all is ok, no errors, but protocol's requirement will call the default implementation and 'old' implemented methods will never be called.

But I also support your suggestion regarding public methods of type extension that conforms to protocol.
This way or another IMO we need a way to show(for reader *and* for compiler) that some methods were implemented just to satisfy the protocol.

···

On 23.05.2016 7:53, Douglas Gregor wrote:

On May 18, 2016, at 12:28 AM, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote:

I'd like to discuss declaration of protocol implementation in types.

Ideas of this pitch is partially based on Erica Sadun's thread:
[Pitch] Requiring proactive overrides for default protocol implementations.
http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496
And on this draft of proposal:
https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a

I had read "Winding down the Swift 3 release" message, but feel like this proposal makes "improvements to the consistency and feel of the language"
and supports the "goal of making Swift 4 as source compatible with Swift 3 as we can reasonably accomplish". Or this can be discussed as 'after Swift 3.0' feature.

The main idea of my proposal

Swift should help us to be explicit about what methods were defined in type specifically to fulfill a protocol requirements. And so we will have more understandable and self-documented code that is explicit regarding the fact of protocol implementation(for reader of our code and for compiler).

Additionally this can help to reduce potential problems/error/misunderstanding in case some protocol requirement(method) were *removed* - in this case (currently) our type will still have a method as implementation but no such requirement in conformed protocol yet.

Details

I propose to introduce *implement* keyword to 'mark' the methods(in type) that were defined in order to conform to protocol.

I like this better than using the “override” or “required” keywprds.

Also, *reimplement* keyword is proposed to reflect the fact that method is declared in *both* : in the type and in protocol extension (only in extension, no definition of the method in protocol itself)

I (personally) still don’t feel like the cases handled by “reimplement” are important to distinguish from “implement”.

Without digging deeply into your rules, I’d like to reiterate my own (personal!) perspective on why I don’t think we need a keyword here. With a few exceptions, one can freely break up a type’s definition into a number of different extensions. A fairly common style I’ve seen it to use a unique extension for each protocol conformance, because it’s great for readability: this is the functionality that is associated with a particular protocol conformance. This style conveys essentially what the “implements” keyword conveys: that the programmer intends to implement the protocol, but it does so without any extra syntax. Moreover, if we assume that this is good style and widely practiced, the compiler can use it as a cue: non-private declarations that are within an extension that states conformance to P, that are similar to some requirement in P but aren’t used to satisfy any require, are suspicious and should produce a warning.

  - Doug