[Review] SE-0164: Remove final support in protocol extensions

Comments in-line below

-- Howard.

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances for
Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might add
a method sinh for example and the user of your library might be using other
numerical libraries as well, one of these others might also provide sinh.
Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh, rather
than extending float with an additional function, and vending types for
more complex things like matrices, rather than extending arrays with dot
products for example. If you vend a type you can easily give access to the
underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter. I
am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

···

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding protocols
and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding
methods and protocols retrospectively

## Revision history

> Version | Date | Comment |

>---------|--------------|--------------|

> Draft 1 | 11 April 2017 | Initial version |

> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |

> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/enum/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be
final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all the
methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {

        func m2P() { print("Int.m2P") }

    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {

        x.m2P()

        return x

    }

Then when used in an external module both the input Int and the output Int
are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required by
the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {

        var value = 0

        func m2P() { print("Int.m2P") }

    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular final extensions are not
exported.

As part of Swift's goal of world domination is that it is meant to be easy
to learn by a process of "successive disclosure". The current inconsistent
behaviour of protocols and extensions hinders this process and is a common
gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There is
some excellent advice March 10, 2007 - Visual Basic Blog
extension-methods-best-practices-extension-methods-part-6/ written by the
VB .NET team when they added extensions to VB .NET. The best-practice
advice can be summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the
suggestions] can (and quite frankly should!) be completely ignored." This
is an important observations, in your own code that is not intended for
reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in
the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This recommendation
is formalised in the proposal by limiting final extensions to be
fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to
Swift terminology provide default implementations for protocol methods. The
proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation
to Swift terminology provide default implementations for protocol methods
that extend other protocols if there is a more specific behaviour that is
relevent. The proposal encourages this by eliminating a major gotcha with
the current implementation, namely the proposal always dispatches via a
Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing
consistence and without loosing the ability to use extensions heavily in
your own one-off code to allow for rapid development. Most of the best
practices are for better libraries, particularly third party, which is an
important area for future Swift growth onto the server side. This proposal
actively encourages this transition to large formal server side code
without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

===================================================

#Proposal: Split extension usage up into implementing methods and adding
methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced
static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be
final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed
as a protocol is copied onto the heap, a pointer to its Vtable added, and
it is passed as a pointer. IE it becomes a class instance. No change needed
for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a final
extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class declaration
is in then the extension and the methods can only have fileprivate or
internal access. This prevents post-hoc extensions from numerous modules
clashing, since they are not exported outside of the module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> > wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < > swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it is
exported then you cannot prevent clashes from two modules, this is a known
problem in C#. Because of this and other problems with C# extensions, this
style of extension were rejected by other language communities (notably
Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

Simple: you put the user code that needs the more accurate library in one
file and import only the more accurate library there, and you put the user
code that needs the more performant library in a separate file and import
only the more performant library there! Swift's devotion to file-based
organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import and/or
disambiguation feature, not for disallowing public retroactive conformance.
A proposal to rip out entirely the ability to vend public APIs with
extensions is simply not going to fly. The core team has committed to a
small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.

···

On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh, rather
than extending float with an additional function, and vending types for
more complex things like matrices, rather than extending arrays with dot
products for example. If you vend a type you can easily give access to the
underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter. I
am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding protocols
and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding
methods and protocols retrospectively

## Revision history

> Version | Date | Comment |

>---------|--------------|--------------|

> Draft 1 | 11 April 2017 | Initial version |

> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |

> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/enum/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {

        func m2P() { print("Int.m2P") }

    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {

        x.m2P()

        return x

    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required
by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {

        var value = 0

        func m2P() { print("Int.m2P") }

    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular final extensions are not
exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There is
some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of the
suggestions] can (and quite frankly should!) be completely ignored." This
is an important observations, in your own code that is not intended for
reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in
the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to
Swift terminology provide default implementations for protocol methods. The
proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation
to Swift terminology provide default implementations for protocol methods
that extend other protocols if there is a more specific behaviour that is
relevent. The proposal encourages this by eliminating a major gotcha with
the current implementation, namely the proposal always dispatches via a
Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing
consistence and without loosing the ability to use extensions heavily in
your own one-off code to allow for rapid development. Most of the best
practices are for better libraries, particularly third party, which is an
important area for future Swift growth onto the server side. This proposal
actively encourages this transition to large formal server side code
without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and adding
methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced
static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed
as a protocol is copied onto the heap, a pointer to its Vtable added, and
it is passed as a pointer. IE it becomes a class instance. No change needed
for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it is
exported then you cannot prevent clashes from two modules, this is a known
problem in C#. Because of this and other problems with C# extensions, this
style of extension were rejected by other language communities (notably
Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

As it stands at the moment splitting to multiple files doesn't work. EG:

ModuleA

A.swift

public protocol P {

func m() -> String

}

extension Int: P {

public func m() -> String {

return "AP.m"

}

}

ModuleB

B.swift

public protocol P {

func m() -> String

}
extension Int: P {

public func m() -> String {

return "BP.m"

}

}

ModuleC

A.swift

import ModuleA

func am(_ i: Int) -> String { return i.m() }

B.swift

import ModuleB

func bm(_ i: Int) -> String { return i.m() }

main.swift

let i = 0

print(am(i))
print(bm(i))

Gives the following errors when built:

sunzero-ln:ModuleC lov080$ swift build
Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA
Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB
Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA
Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA at 1.0.0
Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB
Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB at 1.0.0
Compile Swift Module 'ModuleB' (1 sources)
Compile Swift Module 'ModuleA' (1 sources)
Compile Swift Module 'ModuleC' (3 sources)
/Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleC/Sources/B.swift:3:38: error: ambiguous use of 'm()'
func bm(_ i: Int) -> String { return i.m() }
                                     ^
ModuleA.Int:2:17: note: found this candidate
    public func m() -> String
                ^
ModuleB.Int:2:17: note: found this candidate
    public func m() -> String
                ^
/Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleC/Sources/A.swift:3:38: error: ambiguous use of 'm()'
func am(_ i: Int) -> String { return i.m() }
                                     ^
ModuleA.Int:2:17: note: found this candidate
    public func m() -> String
                ^
ModuleB.Int:2:17: note: found this candidate
    public func m() -> String
                ^
<unknown>:0: error: build had 1 command failures
error: exit(1):
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool
-f /Users/lov080/Google\ Drive/Swift/Examples/Example\ Module\
Clashes/ModuleC/.build/debug.yaml

As you can see that despite each file A and B in ModuleC only importing one
module each all the extensions apply even if not explicitly imported.

  -- Howard.

···

On 18 April 2017 at 11:47, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Simple: you put the user code that needs the more accurate library in one
file and import only the more accurate library there, and you put the user
code that needs the more performant library in a separate file and import
only the more performant library there! Swift's devotion to file-based
organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter. I
am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding protocols
and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history

> Version | Date | Comment |

>---------|--------------|--------------|

> Draft 1 | 11 April 2017 | Initial version |

> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |

> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/enum/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {

        func m2P() { print("Int.m2P") }

    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {

        x.m2P()

        return x

    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required
by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {

        var value = 0

        func m2P() { print("Int.m2P") }

    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular final extensions are not
exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There is
some excellent advice https://blogs.msdn.microsoft.
com/vbteam/2007/03/10/extension-methods-best-
practices-extension-methods-part-6/ written by the VB .NET team when
they added extensions to VB .NET. The best-practice advice can be
summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the
suggestions] can (and quite frankly should!) be completely ignored." This
is an important observations, in your own code that is not intended for
reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised
in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to
Swift terminology provide default implementations for protocol methods. The
proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation
to Swift terminology provide default implementations for protocol methods
that extend other protocols if there is a more specific behaviour that is
relevent. The proposal encourages this by eliminating a major gotcha with
the current implementation, namely the proposal always dispatches via a
Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing
consistence and without loosing the ability to use extensions heavily in
your own one-off code to allow for rapid development. Most of the best
practices are for better libraries, particularly third party, which is an
important area for future Swift growth onto the server side. This proposal
actively encourages this transition to large formal server side code
without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

===================================================

#Proposal: Split extension usage up into implementing methods and adding
methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced
static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed
as a protocol is copied onto the heap, a pointer to its Vtable added, and
it is passed as a pointer. IE it becomes a class instance. No change needed
for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it
is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

+1

Extensions are a great feature and I’m really glad that Swift has them. Conflicts should be handled by improving import and disambiguation features like Xiaodi says which is useful for other cases as well.

-Thorsten

···

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one file and import only the more accurate library there, and you put the user code that needs the more performant library in a separate file and import only the more performant library there! Swift's devotion to file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import and/or disambiguation feature, not for disallowing public retroactive conformance. A proposal to rip out entirely the ability to vend public APIs with extensions is simply not going to fly. The core team has committed to a small standard library and multiple independent core libraries like Foundation. This can only work because Foundation can greatly expand the API of standard library types through extensions.

Your proposal would undo that design decision and require folding Foundation's functionality into the standard library, or rewriting the entire Foundation overlay to encapsulate standard library types instead of extending them. For example, NSString would have to be a separate type that encapsulates String. Yet oodles of work have gone into making NSString seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:
Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful languages do not have extensions. Extensions have been discussed and rejected by successful languages. The .NET guidelines suggest considered cautious use. I have tried to encapsulate the best practice into a language feature.

For instance, I am writing a library that vends additional conformances for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might add a method sinh for example and the user of your library might be using other numerical libraries as well, one of these others might also provide sinh. Which is to be called in the user code by f.sinh? Suppose one library emphasises speed over accuracy and the other vice versa. You really want access to both versions in the user code. This is a situation I have come across a few times in numeric C, Java, and C++ with matrix libraries where code I have worked on has used multiple libraries in the same application for good reason.

I think you would be better vending functions for things like sinh, rather than extending float with an additional function, and vending types for more complex things like matrices, rather than extending arrays with dot products for example. If you vend a type you can easily give access to the underlying type using composition rather than extension or inheritance, there is an example of this in the proposal just above the Justification section..

Your design would eliminate all such libraries, which is a non-starter. I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com <mailto:howard.lovatt@gmail.com>> wrote:
@Brent,

I have updated the proposal to address your concerns, in particular I don't see that retrospectively adding methods and protocols has been removed it has just had its ugly corners rounded. See revised proposal below particularly the end of section "Retrospectively adding protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/enum/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this proposal is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/enum/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the protocol/struct/enum/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents retrospective extensions from numerous modules clashing, since they are not exported outside of the module.

When a type is extended inside a module with a final extension the extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output Int are not extended with P2. However as the Int goes into f it gains P2 conformance and when it leaves it looses P2 conformance. Thus inside and outside the module the behaviour is easily understood and consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final extension, and can easily be used as both a P2 and an Int and does not clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular final extensions are not exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages and the feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. This keeping it small and simple test is what extensions have failed in other languages.

Experience from .NET can however be used to improve extensions. There is some excellent advice Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog written by the VB .NET team when they added extensions to VB .NET. The best-practice advice can be summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the suggestions] can (and quite frankly should!) be completely ignored." This is an important observations, in your own code that is not intended for reuse; go for it, use extensions. The proposal importantly still allows this style of programming and in fact improves it by adding consistent behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The equivalent for Swift is lacking at this stage. Probably because third party libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to Swift terminology provide default implementations for protocol methods. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation to Swift terminology provide default implementations for protocol methods that extend other protocols if there is a more specific behaviour that is relevent. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing consistence and without loosing the ability to use extensions heavily in your own one-off code to allow for rapid development. Most of the best practices are for better libraries, particularly third party, which is an important area for future Swift growth onto the server side. This proposal actively encourages this transition to large formal server side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

===================================================

#Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs and classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also post-hoc adds the protocol.

  2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents post-hoc extensions from numerous modules clashing, since they are not exported outside of the module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com <mailto:brent@architechies.com>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I don't see that retroactive conformance needs to be exportable. If it is exported then you cannot prevent clashes from two modules, this is a known problem in C#. Because of this and other problems with C# extensions, this style of extension were rejected by other language communities (notably Java and Scala).

A better alternative for export is a new class that encapsulates the standard type but with added methods for the protocol to be added. This way there is no clash between modules. EG:

   public protocol P {
       func m() -> String
   }
   public class PInt: P {
       var value = 0
       func m() -> String { return "PI.m" }
   }

Howard, this would be very source-breaking and would fail to achieve fundamental goals of Swift's protocol design. Removing retroactive conformance is no more realistic than removing Objective-C bridging—another feature which introduces various ugly edge cases and tricky behaviors but is also non-negotiable.

--
Brent Royal-Gordon
Architechies

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

Neat. Seems like that'd be a bug.

···

On Wed, Apr 19, 2017 at 9:40 PM, Howard Lovatt <howard.lovatt@gmail.com> wrote:

As it stands at the moment splitting to multiple files doesn't work. EG:

ModuleA

A.swift

public protocol P {

func m() -> String

}

extension Int: P {

public func m() -> String {

return "AP.m"

}

}

ModuleB

B.swift

public protocol P {

func m() -> String

}
extension Int: P {

public func m() -> String {

return "BP.m"

}

}

ModuleC

A.swift

import ModuleA

func am(_ i: Int) -> String { return i.m() }

B.swift

import ModuleB

func bm(_ i: Int) -> String { return i.m() }

main.swift

let i = 0

print(am(i))
print(bm(i))

Gives the following errors when built:

sunzero-ln:ModuleC lov080$ swift build
Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA
Fetching /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB
Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA
Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleA at 1.0.0
Cloning /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB
Resolving /Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleB at 1.0.0
Compile Swift Module 'ModuleB' (1 sources)
Compile Swift Module 'ModuleA' (1 sources)
Compile Swift Module 'ModuleC' (3 sources)
/Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleC/Sources/B.swift:3:38: error: ambiguous use of 'm()'
func bm(_ i: Int) -> String { return i.m() }
                                     ^
ModuleA.Int:2:17: note: found this candidate
    public func m() -> String
                ^
ModuleB.Int:2:17: note: found this candidate
    public func m() -> String
                ^
/Users/lov080/Google Drive/Swift/Examples/Example Module
Clashes/ModuleC/Sources/A.swift:3:38: error: ambiguous use of 'm()'
func am(_ i: Int) -> String { return i.m() }
                                     ^
ModuleA.Int:2:17: note: found this candidate
    public func m() -> String
                ^
ModuleB.Int:2:17: note: found this candidate
    public func m() -> String
                ^
<unknown>:0: error: build had 1 command failures
error: exit(1): /Applications/Xcode.app/Contents/Developer/Toolchains/
XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f
/Users/lov080/Google\ Drive/Swift/Examples/Example\ Module\
Clashes/ModuleC/.build/debug.yaml

As you can see that despite each file A and B in ModuleC only importing
one module each all the extensions apply even if not explicitly imported.

  -- Howard.

On 18 April 2017 at 11:47, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Simple: you put the user code that needs the more accurate library in one
file and import only the more accurate library there, and you put the user
code that needs the more performant library in a separate file and import
only the more performant library there! Swift's devotion to file-based
organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter.
I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history

> Version | Date | Comment |

>---------|--------------|--------------|

> Draft 1 | 11 April 2017 | Initial version |

> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |

> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/enum/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {

        func m2P() { print("Int.m2P") }

    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {

        x.m2P()

        return x

    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required
by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {

        var value = 0

        func m2P() { print("Int.m2P") }

    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There
is some excellent advice https://blogs.msdn.microsoft.c
om/vbteam/2007/03/10/extension-methods-best-practices-
extension-methods-part-6/ written by the VB .NET team when they added
extensions to VB .NET. The best-practice advice can be summarised by the
following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised
in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation
to Swift terminology provide default implementations for protocol methods.
The proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposa
ls/0169-improve-interaction-between-private-declarations-
and-extensions.md.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {

        func mP() -> String

     }

    extension P {

        func mP() -> String { return "P.mP" }

        func mE() -> String { return "P.mE" }

    }

    struct S: P {

        func mP() -> String { return "S.mP" }

        func mE() -> String { return "S.mE" }

    }

    let s = S()

    s.mP() // S.mP as expected

    s.mE() // S.mE as expected

    let p: P = s // Note: s now typed as P

    p.mP() // S.mP as expected

    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A

    extension Int: P {

        func m() -> String { print("A.m") }

    }

In Module B

    extension Int: P {

        func m() -> String { print("B.m") }

    }

In Module C

    import A

    import B // Should this be an error

    let i = 0

    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift

    protocol/struct/class P {

        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension

    }

    extension P {

        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration

    }

Same or other file

    struct S: P {

        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension

    }

    let p: P = S() // Note typed as P

    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {

        func m2P()

    }

    final extension S: P2 { // Note extension marked final

        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2

        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method

    }

Which are called as any other method would be called:

    let s = S()

    s.m2P() // Prints SP2.m2P

    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposa
ls/0169-improve-interaction-between-private-declarations-
and-extensions.md.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >>>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it
is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported and
ad-hoc code reuse, the two areas of concern.

Comments?

···

=================================================================================

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

Version | Date | Comment |
---------|--------------|--------------|
Draft 1 | 11 April 2017 | Initial version |
Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a

protocol - replaced static final extensions with final extensions |

Draft 3 | 17 April 2017 | Added justification section |
Draft 4 | 2 May 2017 | Allow final extensions to be public and allow

ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols retrospectively. The proposal still retains retroactively
adding protocol conformance and ad-hoc code reuse, however these are made
easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its
implemented methods are dispatched using a Vtable for protocols and classes
and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be
final, and can have where clauses and provide inheritable implementations.
Ad-hoc code reuse is supported, in particular if a class/enum/strict
already had a method, m say, and a protocol, P say, required an m then an
extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented
in an extension without the use of the override keyword. This situation
only applies to protocols, for structs/enumerated/classes you cannot
declare in type and implement in an extension at all. This proposal unifies
the behaviour of protocol/struct/enum/class with extensions and also
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions
and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that a
value instance typed as a protocol is copied onto the heap, a pointer to
its Vtable added, and its address passed/copied (i.e. it becomes a class
instance). No change is needed for a class instance typed as a protocol,
which unlike at present can now be passed/copied as a protocol directly.
Think of a protocol as like an abstract class; cannot be instantiated like
an abstract class and which possibly has abstract methods, but in different
in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an existing
method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly final
(as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method cannot
already exist. IE a `final extension` cannot override an existing method or
implement a protocol declared method that lacks an implementation (unless
it also adds the protocol). This is retroactively adding a method. Also see
next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it inherits
all the methods in that protocol that are implemented, e.g. `m`. These
inherited methods must be final. This is ad-hoc code reuse of final methods
when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching.
That is why all methods involved in a `final extension` are final. The
compiler always knows that the method can be called statically and there is
no need for a Vtable entry for any of the methods, it is as though the
methods were declared static but with the more convenient syntax of a
normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is
that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be easy
to learn by a process of "successive disclosure". The current inconsistent
behaviour of protocols and extensions hinders this process and is a common
gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly
rather than via an extension, since under the proposal the extension adds
the declaration to the type so it is a small step to allow the protocol
methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses:
implementing methods and retroactively adding protocols and methods (in
both cases including ad-hoc code reuse). The purpose of this split is to
eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as the
type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file, however
final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <

.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has them.
Conflicts should be handled by improving import and disambiguation features
like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < > swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one
file and import only the more accurate library there, and you put the user
code that needs the more performant library in a separate file and import
only the more performant library there! Swift's devotion to file-based
organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter. I
am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding protocols
and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required
by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular final extensions are not
exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There is
some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of the
suggestions] can (and quite frankly should!) be completely ignored." This
is an important observations, in your own code that is not intended for
reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised
in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to
Swift terminology provide default implementations for protocol methods. The
proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation
to Swift terminology provide default implementations for protocol methods
that extend other protocols if there is a more specific behaviour that is
relevent. The proposal encourages this by eliminating a major gotcha with
the current implementation, namely the proposal always dispatches via a
Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing
consistence and without loosing the ability to use extensions heavily in
your own one-off code to allow for rapid development. Most of the best
practices are for better libraries, particularly third party, which is an
important area for future Swift growth onto the server side. This proposal
actively encourages this transition to large formal server side code
without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and adding
methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced
static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules,
consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed
as a protocol is copied onto the heap, a pointer to its Vtable added, and
it is passed as a pointer. IE it becomes a class instance. No change needed
for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses:
implementing methods and post-hoc adding protocols and methods. Syntax is
added that clarifies the two use cases, the former are termed extensions
and must be in the same file as the type is declared, and the latter are
termed final extensions and can be in any file, however if they are not in
the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it
is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

I'm sorry, it's been a while. What is the harm that you are trying to cure,
and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

···

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> wrote:

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported and
ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow
ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols retrospectively. The proposal still retains retroactively
adding protocol conformance and ad-hoc code reuse, however these are made
easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its
implemented methods are dispatched using a Vtable for protocols and classes
and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be
final, and can have where clauses and provide inheritable implementations.
Ad-hoc code reuse is supported, in particular if a class/enum/strict
already had a method, m say, and a protocol, P say, required an m then an
extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented
in an extension without the use of the override keyword. This situation
only applies to protocols, for structs/enumerated/classes you cannot
declare in type and implement in an extension at all. This proposal unifies
the behaviour of protocol/struct/enum/class with extensions and also
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions
and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that
a value instance typed as a protocol is copied onto the heap, a pointer to
its Vtable added, and its address passed/copied (i.e. it becomes a class
instance). No change is needed for a class instance typed as a protocol,
which unlike at present can now be passed/copied as a protocol directly.
Think of a protocol as like an abstract class; cannot be instantiated like
an abstract class and which possibly has abstract methods, but in different
in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an existing
method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly final
(as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method cannot
already exist. IE a `final extension` cannot override an existing method or
implement a protocol declared method that lacks an implementation (unless
it also adds the protocol). This is retroactively adding a method. Also see
next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it inherits
all the methods in that protocol that are implemented, e.g. `m`. These
inherited methods must be final. This is ad-hoc code reuse of final methods
when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching.
That is why all methods involved in a `final extension` are final. The
compiler always knows that the method can be called statically and there is
no need for a Vtable entry for any of the methods, it is as though the
methods were declared static but with the more convenient syntax of a
normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be easy
to learn by a process of "successive disclosure". The current inconsistent
behaviour of protocols and extensions hinders this process and is a common
gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses:
implementing methods and retroactively adding protocols and methods (in
both cases including ad-hoc code reuse). The purpose of this split is to
eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as the
type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> > wrote:

+1

Extensions are a great feature and I’m really glad that Swift has them.
Conflicts should be handled by improving import and disambiguation features
like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one
file and import only the more accurate library there, and you put the user
code that needs the more performant library in a separate file and import
only the more performant library there! Swift's devotion to file-based
organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter.
I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot
already exist. IE a final extension cannot override an existing method or
implement a protocol declared method that lacks an implementation unless it
also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required
by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There
is some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised
in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation
to Swift terminology provide default implementations for protocol methods.
The proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely
implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name
would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >>>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it
is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both structs and classes, as outlined in the first section of the proposal. This is confusing for beginners and difficult to debug in large code bases, particularly those involving third party libraries were source is not available. I think a lot of the current experience with Swift does not use large code bases or third party libraries because the experience is with App development. As Swift moves to the server side large code bases and third party libraries will become the norm and the problems that result from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I am saying it is undesirable. The Generics Manifesto also lists the behaviour as undesirable. Changes can and should be made for undesirable behaviour, e.g. the exclusivity proposal currently under review and the scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and the payoff of enabling large code bases and third party libraries is huge. The changes would involve:

    i. Moving some extensions from a seperate file into the file were the type was declared. This is good practice anyway and consistent with the behaviour of private, so no big deal. You should be doing this anyway. This would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in extensions to *that* protocol. Easily caught by the compiler and Xcode could do the refactoring.

    ii. Marking retrospective conformance via extensions with final. Because this also means that the methods need to be final there could be some change. However, I would argue change for the good since it clarifies what happens, much like the changes needed for exclusivity are good. Note that since enum and struct methods are already final there is no change here other than adding final. Again a small change that the compiler/Xcode can do. The only area likely to have any issues are retrospective conformance for protocols and classes. This is a small price to pay for something as valuable as using third party libraries.

-- Howard.

···

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the revised integer protocols that were just approved, distinguish between protocol requirements for which default implementations are provided and protocol extension methods which can be shadowed but not overridden. Both are used, and deliberately. Are you proposing to remove this feature? That simply cannot be done, as it would require re-designing vast amounts of the standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> wrote:
I haven't replied to these messages for a while since it has taken some time to formulate a proposal that incorporates the feedback give - thanks for the feedback.

The new proposal allows retroactively added protocols to be exported and ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!
    
The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively. The proposal still retains retroactively adding protocol conformance and ad-hoc code reuse, however these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its implemented methods are dispatched using a Vtable for protocols and classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations. Ad-hoc code reuse is supported, in particular if a class/enum/strict already had a method, m say, and a protocol, P say, required an m then an extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented in an extension without the use of the override keyword. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in an extension at all. This proposal unifies the behaviour of protocol/struct/enum/class with extensions and also prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and its address passed/copied (i.e. it becomes a class instance). No change is needed for a class instance typed as a protocol, which unlike at present can now be passed/copied as a protocol directly. Think of a protocol as like an abstract class; cannot be instantiated like an abstract class and which possibly has abstract methods, but in different in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the Vtable and are statically dispatched, i.e. no change from current Swift for static but final now has the expected meaning for a protocol. Dispatching for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be either in or outside the file in which the protocol/struct/enum/class declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }
    
In same or another file
    
    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method cannot already exist. IE a `final extension` cannot override an existing method or implement a protocol declared method that lacks an implementation (unless it also adds the protocol). This is retroactively adding a method. Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must implement all the methods in that protocol that are not implemented, e.g. `m2`. This is retroactively adding protocol conformance. Also see next point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it inherits all the methods in that protocol that are implemented, e.g. `m`. These inherited methods must be final. This is ad-hoc code reuse of final methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching. That is why all methods involved in a `final extension` are final. The compiler always knows that the method can be called statically and there is no need for a Vtable entry for any of the methods, it is as though the methods were declared static but with the more convenient syntax of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular, the two forms of extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages. The feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. It is this keeping it small and simple test that extensions have failed in other languages, in particular their behaviour is hard to predict in a large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few changes to them to make their behaviour predictable both in terms of third party libraries and in terms of method dispatch when the variable is typed as a protocol. Thereby still providing extensions including retroactive conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses: implementing methods and retroactively adding protocols and methods (in both cases including ad-hoc code reuse). The purpose of this split is to eliminate the problems associated with exceptions that have been well documented both with respect to Swift and other languages. Syntax is added that clarifies their two use cases (implementing methods and retroactively adding):

  1. The former are termed extensions and must be in the same file as the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file, however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in <http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md&gt;\.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> wrote:
+1

Extensions are a great feature and I’m really glad that Swift has them. Conflicts should be handled by improving import and disambiguation features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one file and import only the more accurate library there, and you put the user code that needs the more performant library in a separate file and import only the more performant library there! Swift's devotion to file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import and/or disambiguation feature, not for disallowing public retroactive conformance. A proposal to rip out entirely the ability to vend public APIs with extensions is simply not going to fly. The core team has committed to a small standard library and multiple independent core libraries like Foundation. This can only work because Foundation can greatly expand the API of standard library types through extensions.

Your proposal would undo that design decision and require folding Foundation's functionality into the standard library, or rewriting the entire Foundation overlay to encapsulate standard library types instead of extending them. For example, NSString would have to be a separate type that encapsulates String. Yet oodles of work have gone into making NSString seamlessly bridge to String in the first place.

On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> wrote:
Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful languages do not have extensions. Extensions have been discussed and rejected by successful languages. The .NET guidelines suggest considered cautious use. I have tried to encapsulate the best practice into a language feature.

For instance, I am writing a library that vends additional conformances for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might add a method sinh for example and the user of your library might be using other numerical libraries as well, one of these others might also provide sinh. Which is to be called in the user code by f.sinh? Suppose one library emphasises speed over accuracy and the other vice versa. You really want access to both versions in the user code. This is a situation I have come across a few times in numeric C, Java, and C++ with matrix libraries where code I have worked on has used multiple libraries in the same application for good reason.

I think you would be better vending functions for things like sinh, rather than extending float with an additional function, and vending types for more complex things like matrices, rather than extending arrays with dot products for example. If you vend a type you can easily give access to the underlying type using composition rather than extension or inheritance, there is an example of this in the proposal just above the Justification section..

Your design would eliminate all such libraries, which is a non-starter. I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> wrote:
@Brent,

I have updated the proposal to address your concerns, in particular I don't see that retrospectively adding methods and protocols has been removed it has just had its ugly corners rounded. See revised proposal below particularly the end of section "Retrospectively adding protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/enum/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this proposal is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/enum/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the protocol/struct/enum/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents retrospective extensions from numerous modules clashing, since they are not exported outside of the module.

When a type is extended inside a module with a final extension the extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output Int are not extended with P2. However as the Int goes into f it gains P2 conformance and when it leaves it looses P2 conformance. Thus inside and outside the module the behaviour is easily understood and consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final extension, and can easily be used as both a P2 and an Int and does not clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular final extensions are not exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages and the feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. This keeping it small and simple test is what extensions have failed in other languages.

Experience from .NET can however be used to improve extensions. There is some excellent advice Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog written by the VB .NET team when they added extensions to VB .NET. The best-practice advice can be summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the suggestions] can (and quite frankly should!) be completely ignored." This is an important observations, in your own code that is not intended for reuse; go for it, use extensions. The proposal importantly still allows this style of programming and in fact improves it by adding consistent behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The equivalent for Swift is lacking at this stage. Probably because third party libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to Swift terminology provide default implementations for protocol methods. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation to Swift terminology provide default implementations for protocol methods that extend other protocols if there is a more specific behaviour that is relevent. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing consistence and without loosing the ability to use extensions heavily in your own one-off code to allow for rapid development. Most of the best practices are for better libraries, particularly third party, which is an important area for future Swift growth onto the server side. This proposal actively encourages this transition to large formal server side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

===================================================

#Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs and classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also post-hoc adds the protocol.

  2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents post-hoc extensions from numerous modules clashing, since they are not exported outside of the module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it is exported then you cannot prevent clashes from two modules, this is a known problem in C#. Because of this and other problems with C# extensions, this style of extension were rejected by other language communities (notably Java and Scala).

A better alternative for export is a new class that encapsulates the standard type but with added methods for the protocol to be added. This way there is no clash between modules. EG:

   public protocol P {
       func m() -> String
   }
   public class PInt: P {
       var value = 0
       func m() -> String { return "PI.m" }
   }

Howard, this would be very source-breaking and would fail to achieve fundamental goals of Swift's protocol design. Removing retroactive conformance is no more realistic than removing Objective-C bridging—another feature which introduces various ugly edge cases and tricky behaviors but is also non-negotiable.

--
Brent Royal-Gordon
Architechies

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

--
-- Howard.

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

In your new design, how would you express a protocol which has some
requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.

···

On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both structs
and classes, as outlined in the first section of the proposal. This is
confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I am
saying it is undesirable. The Generics Manifesto also lists the behaviour
as undesirable. Changes can and should be made for undesirable behaviour,
e.g. the exclusivity proposal currently under review and the scoping of
private which has been approved already.

  3. I don't think making the changes required would be that large and the
payoff of enabling large code bases and third party libraries is huge. The
changes would involve:

    i. Moving some extensions from a seperate file into the file were the
type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in
extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported and
ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow
ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods
into two seperate use cases: implementations for methods and adding methods
and protocols retrospectively. The proposal still retains retroactively
adding protocol conformance and ad-hoc code reuse, however these are made
easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its
implemented methods are dispatched using a Vtable for protocols and classes
and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that
a value instance typed as a protocol is copied onto the heap, a pointer to
its Vtable added, and its address passed/copied (i.e. it becomes a class
instance). No change is needed for a class instance typed as a protocol,
which unlike at present can now be passed/copied as a protocol directly.
Think of a protocol as like an abstract class; cannot be instantiated like
an abstract class and which possibly has abstract methods, but in different
in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching.
That is why all methods involved in a `final extension` are final. The
compiler always knows that the method can be called statically and there is
no need for a Vtable entry for any of the methods, it is as though the
methods were declared static but with the more convenient syntax of a
normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to
where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses:
implementing methods and retroactively adding protocols and methods (in
both cases including ad-hoc code reuse). The purpose of this split is to
eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as the
type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has them.
Conflicts should be handled by improving import and disambiguation features
like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional conformances
for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might
add a method sinh for example and the user of your library might be using
other numerical libraries as well, one of these others might also provide
sinh. Which is to be called in the user code by f.sinh? Suppose one library
emphasises speed over accuracy and the other vice versa. You really want
access to both versions in the user code. This is a situation I have come
across a few times in numeric C, Java, and C++ with matrix libraries where
code I have worked on has used multiple libraries in the same application
for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a non-starter.
I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement all
the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output
Int are not extended with P2. However as the Int goes into f it gains P2
conformance and when it leaves it looses P2 conformance. Thus inside and
outside the module the behaviour is easily understood and consistent and
doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There
is some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised
in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation
to Swift terminology provide default implementations for protocol methods.
The proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be
either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> >>>>> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it
is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

I'm not so sure that's true. Which standard library protocols intentionally depend upon certain parts to not be overridable? Are they so pervasive that we wouldn't prefer to just mark those members that need it with a `final` keyword? If John McCall woke up tomorrow with some genius idea of how to make extension methods overridable with zero overhead, would we choose to keep the current design?

That's not to say the proposal at hand is a good idea, but I think you're overselling the current design.

···

On May 3, 2017, at 12:25 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but the fact remains that it _is_ used pervasively in the standard library, and deliberately

--
Brent Royal-Gordon
Architechies

Extension methods are not explicitly part of the protocol requirements, so having them overridable by default based on a type having a method or property with a matching signature is basically duck typing.

A hypothetical example, but if swift didn't define "filter(_)" as part of Sequence, it might mean that an extension adds filter with the predicate indicating that the value is included, while my custom sequence defined a filter method where true from the predicate means the value should be 'filtered out'. Both methods would wind up having identical signatures. Generic algorithms written under the concept that 'filter', added by an extension, is now part of the 'Sequence' contract, would be quite confused that sometimes the behavior of their algorithm reverses.

That method implementations which are not part of the protocol definition define functionality around use of a protocol rather than extending the protocol requirements can be confusing, but to me it has always seemed correct. To have those methods be part of the protocol requirements is changing the protocol requirements.

I tried pitching a proposal a few months ago which attempted not to change the rules but to have the code declare intent and compiler warn if the declared intent seemed wrong. I was surprised it got very little interest. Right now, we have an issue where overriding a class method gives you a nice error if you fat-finger part of the signature, but implementing a protocol with extensions providing default implementations does nothing (either when declaring the protocol extension or implementing the protocol within your type)

-DW

···

On May 3, 2017, at 2:09 AM, Brent Royal-Gordon via swift-evolution <swift-evolution@swift.org> wrote:

On May 3, 2017, at 12:25 AM, Xiaodi Wu via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but the fact remains that it _is_ used pervasively in the standard library, and deliberately

I'm not so sure that's true. Which standard library protocols intentionally depend upon certain parts to not be overridable? Are they so pervasive that we wouldn't prefer to just mark those members that need it with a `final` keyword? If John McCall woke up tomorrow with some genius idea of how to make extension methods overridable with zero overhead, would we choose to keep the current design?

I definitely agree that it's a feature that _can_ be used unwisely, but the
fact remains that it _is_ used pervasively in the standard library, and
deliberately, and that such uses have gone through Swift Evolution and been
approved. So there is really no point in discussing the removal of the
feature, as it simply cannot happen.

···

On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

Being able to forbid overriding is fine, allowing shadowing without a
compiler warning/error is undesirable though. We should not have to dig up
80's discussions about polymorphism to see that changing the actual code
being executed by casting a reference one way or the other is wrong. It may
be instrumentally good for some odd reason to someone, but I cannot see it
as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it
also receives its default implementation, means that casting the instance
of the class to the class type or the protocol type would have different
methods being executed which can easily lead to mistakes beyond just
appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and
API contract and by definition shouldn't really have code in them, but it
is convenient for us as we need to share code between value types...).

In your new design, how would you express a protocol which has some
requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.
On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both
structs and classes, as outlined in the first section of the proposal. This
is confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I
am saying it is undesirable. The Generics Manifesto also lists the
behaviour as undesirable. Changes can and should be made for undesirable
behaviour, e.g. the exclusivity proposal currently under review and the
scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and
the payoff of enabling large code bases and third party libraries is huge.
The changes would involve:

    i. Moving some extensions from a seperate file into the file were the
type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in
extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported and
ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow
ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively. The proposal still retains
retroactively adding protocol conformance and ad-hoc code reuse, however
these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then
its implemented methods are dispatched using a Vtable for protocols and
classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is
that a value instance typed as a protocol is copied onto the heap, a
pointer to its Vtable added, and its address passed/copied (i.e. it becomes
a class instance). No change is needed for a class instance typed as a
protocol, which unlike at present can now be passed/copied as a protocol
directly. Think of a protocol as like an abstract class; cannot be
instantiated like an abstract class and which possibly has abstract
methods, but in different in that it cannot have fields but can be multiply
inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching.
That is why all methods involved in a `final extension` are final. The
compiler always knows that the method can be called statically and there is
no need for a Vtable entry for any of the methods, it is as though the
methods were declared static but with the more convenient syntax of a
normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses:
implementing methods and retroactively adding protocols and methods (in
both cases including ad-hoc code reuse). The purpose of this split is to
eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as
the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >>> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has them.
Conflicts should be handled by improving import and disambiguation features
like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional
conformances for Float and Double. Any numerics library would need to do
the same.

You need to consider this carefully because your numerics library
might add a method sinh for example and the user of your library might be
using other numerical libraries as well, one of these others might also
provide sinh. Which is to be called in the user code by f.sinh? Suppose one
library emphasises speed over accuracy and the other vice versa. You really
want access to both versions in the user code. This is a situation I have
come across a few times in numeric C, Java, and C++ with matrix libraries
where code I have worked on has used multiple libraries in the same
application for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a
non-starter. I am not sure what defects you are trying to solve with this
proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance
to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the
protocol/struct/enum/class declaration then it implements the methods and
is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement
all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the
output Int are not extended with P2. However as the Int goes into f it
gains P2 conformance and when it leaves it looses P2 conformance. Thus
inside and outside the module the behaviour is easily understood and
consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There
is some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is
formalised in the proposal by limiting final extensions to be fileprivate
or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation
to Swift terminology provide default implementations for protocol methods.
The proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon < >>>>>> brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If
it is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

_______________________________________________

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

I don't understand your response. The standard library distinguishes between protocol requirements with default implementations, which can be overridden, and protocol extension methods, which can only be shadowed but not overridden. It is used pervasively, from integers to collections. For example, you can shadow but not override Sequence.contains. This is a deliberate design choice. You are describing this as "undesirable"; however, it is not only highly desired (as expressed by many on this list every time a proposal to change it has come up), it would be impossible to maintain the current design of the standard library without this distinction.

Being able to forbid overriding is fine, allowing shadowing without a compiler warning/error is undesirable though. We should not have to dig up 80's discussions about polymorphism to see that changing the actual code being executed by casting a reference one way or the other is wrong. It may be instrumentally good for some odd reason to someone, but I cannot see it as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it also receives its default implementation, means that casting the instance of the class to the class type or the protocol type would have different methods being executed which can easily lead to mistakes beyond just appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and API contract and by definition shouldn't really have code in them, but it is convenient for us as we need to share code between value types...).

···

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

In your new design, how would you express a protocol which has some requirements that have default implementations which can be overridden and some implemented methods that cannot be overridden? If the answer is that you cannot do that, then there is a problem.

On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> wrote:
You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both structs and classes, as outlined in the first section of the proposal. This is confusing for beginners and difficult to debug in large code bases, particularly those involving third party libraries were source is not available. I think a lot of the current experience with Swift does not use large code bases or third party libraries because the experience is with App development. As Swift moves to the server side large code bases and third party libraries will become the norm and the problems that result from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I am saying it is undesirable. The Generics Manifesto also lists the behaviour as undesirable. Changes can and should be made for undesirable behaviour, e.g. the exclusivity proposal currently under review and the scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and the payoff of enabling large code bases and third party libraries is huge. The changes would involve:

    i. Moving some extensions from a seperate file into the file were the type was declared. This is good practice anyway and consistent with the behaviour of private, so no big deal. You should be doing this anyway. This would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in extensions to *that* protocol. Easily caught by the compiler and Xcode could do the refactoring.

    ii. Marking retrospective conformance via extensions with final. Because this also means that the methods need to be final there could be some change. However, I would argue change for the good since it clarifies what happens, much like the changes needed for exclusivity are good. Note that since enum and struct methods are already final there is no change here other than adding final. Again a small change that the compiler/Xcode can do. The only area likely to have any issues are retrospective conformance for protocols and classes. This is a small price to pay for something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the revised integer protocols that were just approved, distinguish between protocol requirements for which default implementations are provided and protocol extension methods which can be shadowed but not overridden. Both are used, and deliberately. Are you proposing to remove this feature? That simply cannot be done, as it would require re-designing vast amounts of the standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> wrote:
I haven't replied to these messages for a while since it has taken some time to formulate a proposal that incorporates the feedback give - thanks for the feedback.

The new proposal allows retroactively added protocols to be exported and ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!
    
The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively. The proposal still retains retroactively adding protocol conformance and ad-hoc code reuse, however these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its implemented methods are dispatched using a Vtable for protocols and classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations. Ad-hoc code reuse is supported, in particular if a class/enum/strict already had a method, m say, and a protocol, P say, required an m then an extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented in an extension without the use of the override keyword. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in an extension at all. This proposal unifies the behaviour of protocol/struct/enum/class with extensions and also prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and its address passed/copied (i.e. it becomes a class instance). No change is needed for a class instance typed as a protocol, which unlike at present can now be passed/copied as a protocol directly. Think of a protocol as like an abstract class; cannot be instantiated like an abstract class and which possibly has abstract methods, but in different in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the Vtable and are statically dispatched, i.e. no change from current Swift for static but final now has the expected meaning for a protocol. Dispatching for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be either in or outside the file in which the protocol/struct/enum/class declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }
    
In same or another file
    
    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method cannot already exist. IE a `final extension` cannot override an existing method or implement a protocol declared method that lacks an implementation (unless it also adds the protocol). This is retroactively adding a method. Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must implement all the methods in that protocol that are not implemented, e.g. `m2`. This is retroactively adding protocol conformance. Also see next point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it inherits all the methods in that protocol that are implemented, e.g. `m`. These inherited methods must be final. This is ad-hoc code reuse of final methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching. That is why all methods involved in a `final extension` are final. The compiler always knows that the method can be called statically and there is no need for a Vtable entry for any of the methods, it is as though the methods were declared static but with the more convenient syntax of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular, the two forms of extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages. The feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. It is this keeping it small and simple test that extensions have failed in other languages, in particular their behaviour is hard to predict in a large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few changes to them to make their behaviour predictable both in terms of third party libraries and in terms of method dispatch when the variable is typed as a protocol. Thereby still providing extensions including retroactive conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses: implementing methods and retroactively adding protocols and methods (in both cases including ad-hoc code reuse). The purpose of this split is to eliminate the problems associated with exceptions that have been well documented both with respect to Swift and other languages. Syntax is added that clarifies their two use cases (implementing methods and retroactively adding):

  1. The former are termed extensions and must be in the same file as the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file, however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in <http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md&gt;\.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> wrote:
+1

Extensions are a great feature and I’m really glad that Swift has them. Conflicts should be handled by improving import and disambiguation features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one file and import only the more accurate library there, and you put the user code that needs the more performant library in a separate file and import only the more performant library there! Swift's devotion to file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import and/or disambiguation feature, not for disallowing public retroactive conformance. A proposal to rip out entirely the ability to vend public APIs with extensions is simply not going to fly. The core team has committed to a small standard library and multiple independent core libraries like Foundation. This can only work because Foundation can greatly expand the API of standard library types through extensions.

Your proposal would undo that design decision and require folding Foundation's functionality into the standard library, or rewriting the entire Foundation overlay to encapsulate standard library types instead of extending them. For example, NSString would have to be a separate type that encapsulates String. Yet oodles of work have gone into making NSString seamlessly bridge to String in the first place.

On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> wrote:
Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful languages do not have extensions. Extensions have been discussed and rejected by successful languages. The .NET guidelines suggest considered cautious use. I have tried to encapsulate the best practice into a language feature.

For instance, I am writing a library that vends additional conformances for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might add a method sinh for example and the user of your library might be using other numerical libraries as well, one of these others might also provide sinh. Which is to be called in the user code by f.sinh? Suppose one library emphasises speed over accuracy and the other vice versa. You really want access to both versions in the user code. This is a situation I have come across a few times in numeric C, Java, and C++ with matrix libraries where code I have worked on has used multiple libraries in the same application for good reason.

I think you would be better vending functions for things like sinh, rather than extending float with an additional function, and vending types for more complex things like matrices, rather than extending arrays with dot products for example. If you vend a type you can easily give access to the underlying type using composition rather than extension or inheritance, there is an example of this in the proposal just above the Justification section..

Your design would eliminate all such libraries, which is a non-starter. I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> wrote:
@Brent,

I have updated the proposal to address your concerns, in particular I don't see that retrospectively adding methods and protocols has been removed it has just had its ugly corners rounded. See revised proposal below particularly the end of section "Retrospectively adding protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/enum/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this proposal is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/enum/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the protocol/struct/enum/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents retrospective extensions from numerous modules clashing, since they are not exported outside of the module.

When a type is extended inside a module with a final extension the extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output Int are not extended with P2. However as the Int goes into f it gains P2 conformance and when it leaves it looses P2 conformance. Thus inside and outside the module the behaviour is easily understood and consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final extension, and can easily be used as both a P2 and an Int and does not clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular final extensions are not exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages and the feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. This keeping it small and simple test is what extensions have failed in other languages.

Experience from .NET can however be used to improve extensions. There is some excellent advice Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog written by the VB .NET team when they added extensions to VB .NET. The best-practice advice can be summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the suggestions] can (and quite frankly should!) be completely ignored." This is an important observations, in your own code that is not intended for reuse; go for it, use extensions. The proposal importantly still allows this style of programming and in fact improves it by adding consistent behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The equivalent for Swift is lacking at this stage. Probably because third party libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to Swift terminology provide default implementations for protocol methods. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation to Swift terminology provide default implementations for protocol methods that extend other protocols if there is a more specific behaviour that is relevent. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing consistence and without loosing the ability to use extensions heavily in your own one-off code to allow for rapid development. Most of the best practices are for better libraries, particularly third party, which is an important area for future Swift growth onto the server side. This proposal actively encourages this transition to large formal server side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

===================================================

#Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs and classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also post-hoc adds the protocol.

  2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents post-hoc extensions from numerous modules clashing, since they are not exported outside of the module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it is exported then you cannot prevent clashes from two modules, this is a known problem in C#. Because of this and other problems with C# extensions, this style of extension were rejected by other language communities (notably Java and Scala).

A better alternative for export is a new class that encapsulates the standard type but with added methods for the protocol to be added. This way there is no clash between modules. EG:

   public protocol P {
       func m() -> String
   }
   public class PInt: P {
       var value = 0
       func m() -> String { return "PI.m" }
   }

Howard, this would be very source-breaking and would fail to achieve fundamental goals of Swift's protocol design. Removing retroactive conformance is no more realistic than removing Objective-C bridging—another feature which introduces various ugly edge cases and tricky behaviors but is also non-negotiable.

--
Brent Royal-Gordon
Architechies

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

--
-- Howard.

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

I see, you're referring specifically to subclasses and issues with not
bring able to implement protocol requirements with default implementations?
Yes, that's a issue which needs some thought, I think. But it is orthogonal
to the point about protocol extension methods, which is well settled and
certainly out of scope for this phase of Swift evolution.

···

On Wed, May 3, 2017 at 02:33 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 08:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but
the fact remains that it _is_ used pervasively in the standard library, and
deliberately, and that such uses have gone through Swift Evolution and been
approved.

I think there is still sense in discussing it if we care about the
language. I do agree that it is more likely and pragmatic (than removing it
outright) to have a warning about it that people can turn on and treat as
an error if they so choose, but while the core team has always stated "how
else do we share code between structs/value types?" essentially, I am not
sure why this should be allowed by default on class/reference types.
To me it just does not make sense and it is a dangerous compromise we have
and a regression from Objective-C.

So there is really no point in discussing the removal of the feature, as
it simply cannot happen.

On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

Being able to forbid overriding is fine, allowing shadowing without a
compiler warning/error is undesirable though. We should not have to dig up
80's discussions about polymorphism to see that changing the actual code
being executed by casting a reference one way or the other is wrong. It may
be instrumentally good for some odd reason to someone, but I cannot see it
as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it
also receives its default implementation, means that casting the instance
of the class to the class type or the protocol type would have different
methods being executed which can easily lead to mistakes beyond just
appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and
API contract and by definition shouldn't really have code in them, but it
is convenient for us as we need to share code between value types...).

In your new design, how would you express a protocol which has some

requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.

On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both
structs and classes, as outlined in the first section of the proposal. This
is confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I
am saying it is undesirable. The Generics Manifesto also lists the
behaviour as undesirable. Changes can and should be made for undesirable
behaviour, e.g. the exclusivity proposal currently under review and the
scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and
the payoff of enabling large code bases and third party libraries is huge.
The changes would involve:

    i. Moving some extensions from a seperate file into the file were
the type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations
in extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

I haven't replied to these messages for a while since it has taken some

time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported
and ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding
methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and
allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively. The proposal still retains
retroactively adding protocol conformance and ad-hoc code reuse, however
these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then
its implemented methods are dispatched using a Vtable for protocols and
classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is
that a value instance typed as a protocol is copied onto the heap, a
pointer to its Vtable added, and its address passed/copied (i.e. it becomes
a class instance). No change is needed for a class instance typed as a
protocol, which unlike at present can now be passed/copied as a protocol
directly. Think of a protocol as like an abstract class; cannot be
instantiated like an abstract class and which possibly has abstract
methods, but in different in that it cannot have fields but can be multiply
inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already
implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static
dispatching. That is why all methods involved in a `final extension` are
final. The compiler always knows that the method can be called statically
and there is no need for a Vtable entry for any of the methods, it is as
though the methods were declared static but with the more convenient syntax
of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two
uses: implementing methods and retroactively adding protocols and methods
(in both cases including ad-hoc code reuse). The purpose of this split is
to eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as
the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >>>> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has
them. Conflicts should be handled by improving import and disambiguation
features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>>>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.

On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>>>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of
successful languages do not have extensions. Extensions have been discussed
and rejected by successful languages. The .NET guidelines suggest
considered cautious use. I have tried to encapsulate the best practice into
a language feature.

For instance, I am writing a library that vends additional
conformances for Float and Double. Any numerics library would need to do
the same.

You need to consider this carefully because your numerics library
might add a method sinh for example and the user of your library might be
using other numerical libraries as well, one of these others might also
provide sinh. Which is to be called in the user code by f.sinh? Suppose one
library emphasises speed over accuracy and the other vice versa. You really
want access to both versions in the user code. This is a situation I have
come across a few times in numeric C, Java, and C++ with matrix libraries
where code I have worked on has used multiple libraries in the same
application for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a
non-starter. I am not sure what defects you are trying to solve with this
proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular
I don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance
to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the
protocol/struct/enum/class declaration then it implements the methods and
is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement
all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the
output Int are not extended with P2. However as the Int goes into f it
gains P2 conformance and when it leaves it looses P2 conformance. Thus
inside and outside the module the behaviour is easily understood and
consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using
the current, April 2017, TIOBE Index - TIOBE index
of job adverts for programmers the languages that are in demand are: Java
15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual
Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl
2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well
for a new language and is already above Objective-C at 14th. However there
is obviously a long way to go and the purpose of this proposal is to help
with this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to
be easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions.
There is some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is
formalised in the proposal by limiting final extensions to be fileprivate
or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions."
Translation to Swift terminology provide default implementations for
protocol methods. The proposal encourages this by eliminating a major
gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon < >>>>>>> brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>>>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If
it is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky beha

I definitely agree that it's a feature that _can_ be used unwisely, but the fact remains that it _is_ used pervasively in the standard library, and deliberately, and that such uses have gone through Swift Evolution and been approved.

I think there is still sense in discussing it if we care about the language. I do agree that it is more likely and pragmatic (than removing it outright) to have a warning about it that people can turn on and treat as an error if they so choose, but while the core team has always stated "how else do we share code between structs/value types?" essentially, I am not sure why this should be allowed by default on class/reference types.
To me it just does not make sense and it is a dangerous compromise we have and a regression from Objective-C.

···

Sent from my iPhone

On 3 May 2017, at 08:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

So there is really no point in discussing the removal of the feature, as it simply cannot happen.

On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

I don't understand your response. The standard library distinguishes between protocol requirements with default implementations, which can be overridden, and protocol extension methods, which can only be shadowed but not overridden. It is used pervasively, from integers to collections. For example, you can shadow but not override Sequence.contains. This is a deliberate design choice. You are describing this as "undesirable"; however, it is not only highly desired (as expressed by many on this list every time a proposal to change it has come up), it would be impossible to maintain the current design of the standard library without this distinction.

Being able to forbid overriding is fine, allowing shadowing without a compiler warning/error is undesirable though. We should not have to dig up 80's discussions about polymorphism to see that changing the actual code being executed by casting a reference one way or the other is wrong. It may be instrumentally good for some odd reason to someone, but I cannot see it as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it also receives its default implementation, means that casting the instance of the class to the class type or the protocol type would have different methods being executed which can easily lead to mistakes beyond just appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and API contract and by definition shouldn't really have code in them, but it is convenient for us as we need to share code between value types...).

In your new design, how would you express a protocol which has some requirements that have default implementations which can be overridden and some implemented methods that cannot be overridden? If the answer is that you cannot do that, then there is a problem.

On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> wrote:
You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both structs and classes, as outlined in the first section of the proposal. This is confusing for beginners and difficult to debug in large code bases, particularly those involving third party libraries were source is not available. I think a lot of the current experience with Swift does not use large code bases or third party libraries because the experience is with App development. As Swift moves to the server side large code bases and third party libraries will become the norm and the problems that result from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I am saying it is undesirable. The Generics Manifesto also lists the behaviour as undesirable. Changes can and should be made for undesirable behaviour, e.g. the exclusivity proposal currently under review and the scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and the payoff of enabling large code bases and third party libraries is huge. The changes would involve:

    i. Moving some extensions from a seperate file into the file were the type was declared. This is good practice anyway and consistent with the behaviour of private, so no big deal. You should be doing this anyway. This would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in extensions to *that* protocol. Easily caught by the compiler and Xcode could do the refactoring.

    ii. Marking retrospective conformance via extensions with final. Because this also means that the methods need to be final there could be some change. However, I would argue change for the good since it clarifies what happens, much like the changes needed for exclusivity are good. Note that since enum and struct methods are already final there is no change here other than adding final. Again a small change that the compiler/Xcode can do. The only area likely to have any issues are retrospective conformance for protocols and classes. This is a small price to pay for something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the revised integer protocols that were just approved, distinguish between protocol requirements for which default implementations are provided and protocol extension methods which can be shadowed but not overridden. Both are used, and deliberately. Are you proposing to remove this feature? That simply cannot be done, as it would require re-designing vast amounts of the standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> wrote:
I haven't replied to these messages for a while since it has taken some time to formulate a proposal that incorporates the feedback give - thanks for the feedback.

The new proposal allows retroactively added protocols to be exported and ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!
    
The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively. The proposal still retains retroactively adding protocol conformance and ad-hoc code reuse, however these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then its implemented methods are dispatched using a Vtable for protocols and classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations. Ad-hoc code reuse is supported, in particular if a class/enum/strict already had a method, m say, and a protocol, P say, required an m then an extension that added P would not need to provide m (i.e. as at present).

In a protocol at present you can declare a method that is then implemented in an extension without the use of the override keyword. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in an extension at all. This proposal unifies the behaviour of protocol/struct/enum/class with extensions and also prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and its address passed/copied (i.e. it becomes a class instance). No change is needed for a class instance typed as a protocol, which unlike at present can now be passed/copied as a protocol directly. Think of a protocol as like an abstract class; cannot be instantiated like an abstract class and which possibly has abstract methods, but in different in that it cannot have fields but can be multiply inherited.

Static and final methods implemented in extensions are not part of the Vtable and are statically dispatched, i.e. no change from current Swift for static but final now has the expected meaning for a protocol. Dispatching for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be either in or outside the file in which the protocol/struct/enum/class declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }
    
In same or another file
    
    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method cannot already exist. IE a `final extension` cannot override an existing method or implement a protocol declared method that lacks an implementation (unless it also adds the protocol). This is retroactively adding a method. Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must implement all the methods in that protocol that are not implemented, e.g. `m2`. This is retroactively adding protocol conformance. Also see next point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it inherits all the methods in that protocol that are implemented, e.g. `m`. These inherited methods must be final. This is ad-hoc code reuse of final methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching. That is why all methods involved in a `final extension` are final. The compiler always knows that the method can be called statically and there is no need for a Vtable entry for any of the methods, it is as though the methods were declared static but with the more convenient syntax of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular, the two forms of extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages. The feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. It is this keeping it small and simple test that extensions have failed in other languages, in particular their behaviour is hard to predict in a large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few changes to them to make their behaviour predictable both in terms of third party libraries and in terms of method dispatch when the variable is typed as a protocol. Thereby still providing extensions including retroactive conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses: implementing methods and retroactively adding protocols and methods (in both cases including ad-hoc code reuse). The purpose of this split is to eliminate the problems associated with exceptions that have been well documented both with respect to Swift and other languages. Syntax is added that clarifies their two use cases (implementing methods and retroactively adding):

  1. The former are termed extensions and must be in the same file as the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file, however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in <http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md&gt;\.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> wrote:
+1

Extensions are a great feature and I’m really glad that Swift has them. Conflicts should be handled by improving import and disambiguation features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution <swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in one file and import only the more accurate library there, and you put the user code that needs the more performant library in a separate file and import only the more performant library there! Swift's devotion to file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import and/or disambiguation feature, not for disallowing public retroactive conformance. A proposal to rip out entirely the ability to vend public APIs with extensions is simply not going to fly. The core team has committed to a small standard library and multiple independent core libraries like Foundation. This can only work because Foundation can greatly expand the API of standard library types through extensions.

Your proposal would undo that design decision and require folding Foundation's functionality into the standard library, or rewriting the entire Foundation overlay to encapsulate standard library types instead of extending them. For example, NSString would have to be a separate type that encapsulates String. Yet oodles of work have gone into making NSString seamlessly bridge to String in the first place.

On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> wrote:
Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful languages do not have extensions. Extensions have been discussed and rejected by successful languages. The .NET guidelines suggest considered cautious use. I have tried to encapsulate the best practice into a language feature.

For instance, I am writing a library that vends additional conformances for Float and Double. Any numerics library would need to do the same.

You need to consider this carefully because your numerics library might add a method sinh for example and the user of your library might be using other numerical libraries as well, one of these others might also provide sinh. Which is to be called in the user code by f.sinh? Suppose one library emphasises speed over accuracy and the other vice versa. You really want access to both versions in the user code. This is a situation I have come across a few times in numeric C, Java, and C++ with matrix libraries where code I have worked on has used multiple libraries in the same application for good reason.

I think you would be better vending functions for things like sinh, rather than extending float with an additional function, and vending types for more complex things like matrices, rather than extending arrays with dot products for example. If you vend a type you can easily give access to the underlying type using composition rather than extension or inheritance, there is an example of this in the proposal just above the Justification section..

Your design would eliminate all such libraries, which is a non-starter. I am not sure what defects you are trying to solve with this proposal.

I am trying to make Swift more consistent, easier to learn, and to encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> wrote:
@Brent,

I have updated the proposal to address your concerns, in particular I don't see that retrospectively adding methods and protocols has been removed it has just had its ugly corners rounded. See revised proposal below particularly the end of section "Retrospectively adding protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the protocol/struct/enum/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs/enumerated/classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/enum/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this proposal is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/enum/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the protocol/struct/enum/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents retrospective extensions from numerous modules clashing, since they are not exported outside of the module.

When a type is extended inside a module with a final extension the extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the output Int are not extended with P2. However as the Int goes into f it gains P2 conformance and when it leaves it looses P2 conformance. Thus inside and outside the module the behaviour is easily understood and consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is required by the user of a library; then it can simply and safely be provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final extension, and can easily be used as both a P2 and an Int and does not clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the current, April 2017, TIOBE Index - TIOBE index of job adverts for programmers the languages that are in demand are: Java 15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a new language and is already above Objective-C at 14th. However there is obviously a long way to go and the purpose of this proposal is to help with this climb.

A characteristic of many of the languages above Swift in the Tiobe Index is that they have major third party libraries; for some languages they are almost defined by their third part libraries, e.g. Ruby for Rails. A major part of this proposal is to make extensions safe when using multiple libraries from different venders. In particular final extensions are not exported.

As part of Swift's goal of world domination is that it is meant to be easy to learn by a process of "successive disclosure". The current inconsistent behaviour of protocols and extensions hinders this process and is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages for example. Since .NET popularised extensions they have been discussed by other language communities, particularly Java and Scala, and in the academic community (normally termed the Expression Problem) however they have not proved popular because of the problems they cause. Nearly all languages have a strong bias towards keeping the language small and simple and trade of the advantages of a feature against the disadvantages and the feature only makes it into the language if it offers many advantages, has few disadvantages, and is not heavily overlapping with other features. This keeping it small and simple test is what extensions have failed in other languages.

Experience from .NET can however be used to improve extensions. There is some excellent advice Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog written by the VB .NET team when they added extensions to VB .NET. The best-practice advice can be summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of the suggestions] can (and quite frankly should!) be completely ignored." This is an important observations, in your own code that is not intended for reuse; go for it, use extensions. The proposal importantly still allows this style of programming and in fact improves it by adding consistent behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The equivalent for Swift is lacking at this stage. Probably because third party libraries are rare.

  2. "Be wary of extension methods." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  3. "Put extension methods into their own namespace." This recommendation is formalised in the proposal by limiting final extensions to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation to Swift terminology provide default implementations for protocol methods. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible." Translation to Swift terminology provide default implementations for protocol methods that extend other protocols if there is a more specific behaviour that is relevent. The proposal encourages this by eliminating a major gotcha with the current implementation, namely the proposal always dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst increasing consistence and without loosing the ability to use extensions heavily in your own one-off code to allow for rapid development. Most of the best practices are for better libraries, particularly third party, which is an important area for future Swift growth onto the server side. This proposal actively encourages this transition to large formal server side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

===================================================

#Proposal: Split extension usage up into implementing methods and adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol - replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension methods into two seperate use cases: implementations for methods and adding methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class declaration then it implements the methods and is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the extension, under this proposal it is an error to include a declaration in a type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can be final, and can have where clauses and provide inheritable implementations.

In a protocol at present there is a difference in behaviour between a protocol that declares a method that is then implemented in an extension and a protocol that just has the method implemented in an extension and no declaration. This situation only applies to protocols, for structs and classes you cannot declare in type and implement in extensions. The proposal unifies the behaviour of protocol/struct/class with extensions and prevents the error of a minor typo between the protocol and extension adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance typed as a protocol is copied onto the heap, a pointer to its Vtable added, and it is passed as a pointer. IE it becomes a class instance. No change needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can be either in or outside the file in which the protocol/struct/class declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final, completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a final extension cannot override an existing method or implement a protocol declared method that lacks an implementation unless it also post-hoc adds the protocol.

  2. Adds a protocol then it must implement all the methods in that protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class declaration is in then the extension and the methods can only have fileprivate or internal access. This prevents post-hoc extensions from numerous modules clashing, since they are not exported outside of the module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols directly rather than via an extension, since under the proposal the extension adds the declaration to the type so it is a small step to allow the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two uses: implementing methods and post-hoc adding protocols and methods. Syntax is added that clarifies the two use cases, the former are termed extensions and must be in the same file as the type is declared, and the latter are termed final extensions and can be in any file, however if they are not in the type's file the they can only have fileprivate or internal access.

Note the distinction between an extension in the same file and in a separate file is consistent with the philosophy that there is special status to the same file as proposed for private in https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md\.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon <brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution <swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If it is exported then you cannot prevent clashes from two modules, this is a known problem in C#. Because of this and other problems with C# extensions, this style of extension were rejected by other language communities (notably Java and Scala).

A better alternative for export is a new class that encapsulates the standard type but with added methods for the protocol to be added. This way there is no clash between modules. EG:

   public protocol P {
       func m() -> String
   }
   public class PInt: P {
       var value = 0
       func m() -> String { return "PI.m" }
   }

Howard, this would be very source-breaking and would fail to achieve fundamental goals of Swift's protocol design. Removing retroactive conformance is no more realistic than removing Objective-C bridging—another feature which introduces various ugly edge cases and tricky behaviors but is also non-negotiable.

--
Brent Royal-Gordon
Architechies

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

--
-- Howard.

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

Well, the revised integer protocols that were just approved do just that:
some functions are defaults and others cannot be overridden. Smart shifts,
for example, are deliberately not customization points. This is also the
case for Equatable: you get to define ==, but != is not a protocol
requirement and cannot be overridden. A very long list of algorithms on
Sequence and Collection are also implemented in this way (contains,
elementsEqual, enumerated, first, flatMap, lexicographicallyPrecedes, min,
max, reduce, reversed, sorted...). So, at least equatables, numbers,
sequences, and collections depend on this design--I'd call that pervasive.
And these are just the protocols I've worked with in the last two days; I
haven't even looked at the documentation for others.

It serves a real purpose. As has been said before, protocols are not mere
bags of syntax. However, the compiler cannot enforce arbitrary semantic
requirements. This feature allows protocols to guarantee the semantics of
particular members. It is how you can know with complete certainty while
writing a generic algorithm that a == b implies !(a != b) for all equatable
values. Conceptually, protocol extension methods are exactly what their
name suggests: they are definitive implementations of generic algorithms
that make use of the guarantees of a protocol; they are not placeholder
implementations of a requirement that constitutes a part of the protocol
itself. How else would you provide functionality that extends a protocol as
you would a type?

And no, we wouldn't prefer to just mark all of those members as "final".
That was just settled in SE-0164; once upon a time, it was required to do
so, but that was actually tried and backed out, and now the last vestiges
of that legacy have literally just been slated for removal with community
approval.

···

On Wed, May 3, 2017 at 03:09 Brent Royal-Gordon <brent@architechies.com> wrote:

On May 3, 2017, at 12:25 AM, Xiaodi Wu via swift-evolution < > swift-evolution@swift.org> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but
the fact remains that it _is_ used pervasively in the standard library, and
deliberately

I'm not so sure that's true. Which standard library protocols
intentionally depend upon certain parts to not be overridable? Are they so
pervasive that we wouldn't prefer to just mark those members that need it
with a `final` keyword? If John McCall woke up tomorrow with some genius
idea of how to make extension methods overridable with zero overhead, would
we choose to keep the current design?

That's not to say the proposal at hand is a good idea, but I think you're
overselling the current design.

--
Brent Royal-Gordon
Architechies

Casts changing behavior isn't what anyone sets out to support, but it is
the inevitable result of a desired feature: protocol extensions.

If it is desired--and it is--to allow generic algorithms to be provided for
all conforming types of a protocol, and it is desired that such extensions
shouldn't break any conforming types (and they must not, or else the
standard library can never offer additional functionality for collections
(for example) while promising source compatibility), then these
implementations _must_ be non-overridable but shadowable.

···

On Wed, May 3, 2017 at 03:25 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 09:15, Howard Lovatt <howard.lovatt@gmail.com> wrote:

@Goffredo,

"but while the core team has always stated "how else do we share code
between structs/value types?" The proposal provides a way to do this safely

My point is that overloading (pun half intended) protocols / protocol
extensions to deliver that (it is not bad to desire not to have lots of
boilerplate and/or duplicated code to share functionality across value
types implementations) does create a scenario where the feature is not only
dangerous, but incorrect too. I repeat myself often, but I fail to see how
anyone would see casting changing the execution path as a positive (unless
they are looking for ammunition to get rid of OOP ;)).

  -- Howard.

On 3 May 2017 at 17:33, Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 08:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but
the fact remains that it _is_ used pervasively in the standard library, and
deliberately, and that such uses have gone through Swift Evolution and been
approved.

I think there is still sense in discussing it if we care about the
language. I do agree that it is more likely and pragmatic (than removing it
outright) to have a warning about it that people can turn on and treat as
an error if they so choose, but while the core team has always stated "how
else do we share code between structs/value types?" essentially, I am not
sure why this should be allowed by default on class/reference types.
To me it just does not make sense and it is a dangerous compromise we
have and a regression from Objective-C.

So there is really no point in discussing the removal of the feature, as
it simply cannot happen.
On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution < >>> swift-evolution@swift.org> wrote:

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

Being able to forbid overriding is fine, allowing shadowing without a
compiler warning/error is undesirable though. We should not have to dig up
80's discussions about polymorphism to see that changing the actual code
being executed by casting a reference one way or the other is wrong. It may
be instrumentally good for some odd reason to someone, but I cannot see it
as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it
also receives its default implementation, means that casting the instance
of the class to the class type or the protocol type would have different
methods being executed which can easily lead to mistakes beyond just
appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and
API contract and by definition shouldn't really have code in them, but it
is convenient for us as we need to share code between value types...).

In your new design, how would you express a protocol which has some
requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.
On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both
structs and classes, as outlined in the first section of the proposal. This
is confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I
am saying it is undesirable. The Generics Manifesto also lists the
behaviour as undesirable. Changes can and should be made for undesirable
behaviour, e.g. the exclusivity proposal currently under review and the
scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and
the payoff of enabling large code bases and third party libraries is huge.
The changes would involve:

    i. Moving some extensions from a seperate file into the file were
the type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations
in extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including
the revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> >>>> wrote:

I haven't replied to these messages for a while since it has taken
some time to formulate a proposal that incorporates the feedback give -
thanks for the feedback.

The new proposal allows retroactively added protocols to be exported
and ad-hoc code reuse, the two areas of concern.

Comments?

=================================================================================

# Proposal: Split extension into implementing methods and adding
methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and
allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively. The proposal still retains
retroactively adding protocol conformance and ad-hoc code reuse, however
these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then
its implemented methods are dispatched using a Vtable for protocols and
classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is
that a value instance typed as a protocol is copied onto the heap, a
pointer to its Vtable added, and its address passed/copied (i.e. it becomes
a class instance). No change is needed for a class instance typed as a
protocol, which unlike at present can now be passed/copied as a protocol
directly. Think of a protocol as like an abstract class; cannot be
instantiated like an abstract class and which possibly has abstract
methods, but in different in that it cannot have fields but can be multiply
inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already
implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static
dispatching. That is why all methods involved in a `final extension` are
final. The compiler always knows that the method can be called statically
and there is no need for a Vtable entry for any of the methods, it is as
though the methods were declared static but with the more convenient syntax
of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a
few changes to them to make their behaviour predictable both in terms of
third party libraries and in terms of method dispatch when the variable is
typed as a protocol. Thereby still providing extensions including
retroactive conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two
uses: implementing methods and retroactively adding protocols and methods
(in both cases including ad-hoc code reuse). The purpose of this split is
to eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as
the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
http://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
>.

=================================================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >>>>> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has
them. Conflicts should be handled by improving import and disambiguation
features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>>>>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>>>>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of
successful languages do not have extensions. Extensions have been discussed
and rejected by successful languages. The .NET guidelines suggest
considered cautious use. I have tried to encapsulate the best practice into
a language feature.

For instance, I am writing a library that vends additional
conformances for Float and Double. Any numerics library would need to do
the same.

You need to consider this carefully because your numerics library
might add a method sinh for example and the user of your library might be
using other numerical libraries as well, one of these others might also
provide sinh. Which is to be called in the user code by f.sinh? Suppose one
library emphasises speed over accuracy and the other vice versa. You really
want access to both versions in the user code. This is a situation I have
come across a few times in numeric C, Java, and C++ with matrix libraries
where code I have worked on has used multiple libraries in the same
application for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a
non-starter. I am not sure what defects you are trying to solve with this
proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>>>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular
I don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance
to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the
protocol/struct/enum/class declaration then it implements the methods and
is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override
required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement
all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the
output Int are not extended with P2. However as the Int goes into f it
gains P2 conformance and when it leaves it looses P2 conformance. Thus
inside and outside the module the behaviour is easily understood and
consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using
the current, April 2017, TIOBE Index - TIOBE index
of job adverts for programmers the languages that are in demand are: Java
15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual
Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl
2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well
for a new language and is already above Objective-C at 14th. However there
is obviously a long way to go and the purpose of this proposal is to help
with this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to
be easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions.
There is some excellent advice
Extension Methods Best Practices (Extension Methods Part 6) - Visual Basic Blog
written by the VB .NET team when they added extensions to VB .NET. The
best-practice advice can be summarised by the following quotes from the
reference:

  0. "In most real world applications these suggestions [the rest
of the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is
formalised in the proposal by limiting final extensions to be fileprivate
or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions."
Translation to Swift terminology provide default implementations for
protocol methods. The proposal encourages this by eliminating a major
gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override
required because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE
a final extension cannot override an existing method or implement a
protocol declared method that lacks an implementation unless it also
post-hoc adds the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
https://github.com/apple/swift-evolution/blob/master/proposals/0169-improve-interaction-between-private-declarations-and-extensions.md
.

I should add, the reason final is inapt in this situation is at least
twofold.

The first is, of course, that this makes it impossible to guarantee source
compatibility and offer additional functionality in a protocol extension,
since any such addition would break unknowable amounts of existing code.
Consider if we wanted to add a commonly requested convenience function to
Collection in the standard library. Since it is so commonly useful and
doesn't currently exist in the standard library, it is very likely that
numerous people have written their own extensions for one or more concrete
types (say, Array). It would therefore not be possible to add this to the
standard library as an extension on Collection unless (a) we pick a silly
name that we know no one would call this function, which is
counterintuitive, as ideally we want to pick an obvious name that everyone
would call this function; or (b) we make it a protocol requirement with a
default implementation, which is both not what it really is (conceptually,
it's not something that all things need to do in order to be a bona fide
collection, for which we can give just a placeholder default; rather, it's
a neat thing that all bona fide collections can do, and we are implementing
the specific neat thing and not a placeholder to be refined later) and it
would run into the second issue.

The second issue to do with why final is inapt relates to the fact that
protocols are not hierarchically inherited but are meant to be composable
without the problems of multiple inheritance. For instance, the following
is possible--and should be:

protocol P {
}

extension P {
    func f() {
        print("42")
    }
}

protocol Q {
}

extension Q {
    func f() {
        print("43")
    }
}

struct S : P, Q {
}

let s = S()

(s as P).f()
(s as Q).f()

If f were either final or a protocol requirement, barriers would arise due
to clashing definitions. Again, this has source compatibility implications.
It also places limits on the composability and evolution of protocols where
today there aren't any.

···

On Wed, May 3, 2017 at 04:00 Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

Well, the revised integer protocols that were just approved do just that:
some functions are defaults and others cannot be overridden. Smart shifts,
for example, are deliberately not customization points. This is also the
case for Equatable: you get to define ==, but != is not a protocol
requirement and cannot be overridden. A very long list of algorithms on
Sequence and Collection are also implemented in this way (contains,
elementsEqual, enumerated, first, flatMap, lexicographicallyPrecedes, min,
max, reduce, reversed, sorted...). So, at least equatables, numbers,
sequences, and collections depend on this design--I'd call that pervasive.
And these are just the protocols I've worked with in the last two days; I
haven't even looked at the documentation for others.

It serves a real purpose. As has been said before, protocols are not mere
bags of syntax. However, the compiler cannot enforce arbitrary semantic
requirements. This feature allows protocols to guarantee the semantics of
particular members. It is how you can know with complete certainty while
writing a generic algorithm that a == b implies !(a != b) for all equatable
values. Conceptually, protocol extension methods are exactly what their
name suggests: they are definitive implementations of generic algorithms
that make use of the guarantees of a protocol; they are not placeholder
implementations of a requirement that constitutes a part of the protocol
itself. How else would you provide functionality that extends a protocol as
you would a type?

And no, we wouldn't prefer to just mark all of those members as "final".
That was just settled in SE-0164; once upon a time, it was required to do
so, but that was actually tried and backed out, and now the last vestiges
of that legacy have literally just been slated for removal with community
approval.

On Wed, May 3, 2017 at 03:09 Brent Royal-Gordon <brent@architechies.com> > wrote:

On May 3, 2017, at 12:25 AM, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but
the fact remains that it _is_ used pervasively in the standard library, and
deliberately

I'm not so sure that's true. Which standard library protocols
intentionally depend upon certain parts to not be overridable? Are they so
pervasive that we wouldn't prefer to just mark those members that need it
with a `final` keyword? If John McCall woke up tomorrow with some genius
idea of how to make extension methods overridable with zero overhead, would
we choose to keep the current design?

That's not to say the proposal at hand is a good idea, but I think you're
overselling the current design.

--
Brent Royal-Gordon
Architechies

Two points:

  1. The proposal allows for final extensions that work as expected, same
as they would for a class.

  2. I would argue that the behaviour of `contains` is high undesirable and
should be changed (whether approved by Swift Evolution or not). I don't now
why it is the way it is, probably for expediency rather than desirability.
See below for how horrible the situation currently is:

// A sequence that can benefit from optimized implementation of its methods.
// In example just `contains` and `filter` optimised, but could be many
more methods.
struct SequenceOfOneInt: Sequence, IteratorProtocol {
    let value: Int
    private var read = false

    init(_ value: Int) { self.value = value }

    mutating func next() -> Int? {
        if read { return nil }
        read = true
        return value
    }

    func contains(_ x: Int) -> Bool {
        print("Optimised: ", terminator: "") // Note when optimised version
called
        if x == value { return true }
        return false
    }

    func filter(_ isIncluded: (Int) throws -> Bool) rethrows -> [Int] {
        print("Optimised: ", terminator: "") // Note when optimised version
called
        return try isIncluded(value) ? [value] :
    }
}

let s = SequenceOfOneInt(3)

print(s.contains(3)) // Optimised: true
print(s.filter({ $0 < 5 })) // Optimised: [3]

func sPrint<S: Sequence>(_ s: S) where S.Iterator.Element == Int {
    print(s.contains(3))
    print(s.filter({ $0 < 5 }))
}
sPrint(s) // true - i.e. optimised version not used!!!
                                    // Optimised: [3]

Surely this behaviour is not desirable, `filter` and `contains` are treated
identically in the code above and because of some vagary of implementation
of `contains` we get unwanted and very hard to debug behaviour.

The proposal would make both `contains` and `filter` behave as `filter` now
does, i.e. the desirable behaviour.

  -- Howard.

···

On 3 May 2017 at 10:44, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

In your new design, how would you express a protocol which has some
requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.

On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> > wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both
structs and classes, as outlined in the first section of the proposal. This
is confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I
am saying it is undesirable. The Generics Manifesto also lists the
behaviour as undesirable. Changes can and should be made for undesirable
behaviour, e.g. the exclusivity proposal currently under review and the
scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and
the payoff of enabling large code bases and third party libraries is huge.
The changes would involve:

    i. Moving some extensions from a seperate file into the file were the
type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations in
extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported and
ad-hoc code reuse, the two areas of concern.

Comments?

============================================================

# Proposal: Split extension into implementing methods and adding methods
and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to a
protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and allow
ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively. The proposal still retains
retroactively adding protocol conformance and ad-hoc code reuse, however
these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then
its implemented methods are dispatched using a Vtable for protocols and
classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is
that a value instance typed as a protocol is copied onto the heap, a
pointer to its Vtable added, and its address passed/copied (i.e. it becomes
a class instance). No change is needed for a class instance typed as a
protocol, which unlike at present can now be passed/copied as a protocol
directly. Think of a protocol as like an abstract class; cannot be
instantiated like an abstract class and which possibly has abstract
methods, but in different in that it cannot have fields but can be multiply
inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static dispatching.
That is why all methods involved in a `final extension` are final. The
compiler always knows that the method can be called statically and there is
no need for a Vtable entry for any of the methods, it is as though the
methods were declared static but with the more convenient syntax of a
normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe Index
is that they have major third party libraries; for some languages they are
almost defined by their third part libraries, e.g. Ruby for Rails. A major
part of this proposal is to make extensions safe when using multiple
libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET languages
for example. Since .NET popularised extensions they have been discussed by
other language communities, particularly Java and Scala, and in the
academic community (normally termed the Expression Problem) however they
have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols, extensions
could be allowed to add method declarations without bodies to protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two uses:
implementing methods and retroactively adding protocols and methods (in
both cases including ad-hoc code reuse). The purpose of this split is to
eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as
the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md>.

============================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >>> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has them.
Conflicts should be handled by improving import and disambiguation features
like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of successful
languages do not have extensions. Extensions have been discussed and
rejected by successful languages. The .NET guidelines suggest considered
cautious use. I have tried to encapsulate the best practice into a language
feature.

For instance, I am writing a library that vends additional
conformances for Float and Double. Any numerics library would need to do
the same.

You need to consider this carefully because your numerics library
might add a method sinh for example and the user of your library might be
using other numerical libraries as well, one of these others might also
provide sinh. Which is to be called in the user code by f.sinh? Suppose one
library emphasises speed over accuracy and the other vice versa. You really
want access to both versions in the user code. This is a situation I have
come across a few times in numeric C, Java, and C++ with matrix libraries
where code I have worked on has used multiple libraries in the same
application for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a
non-starter. I am not sure what defects you are trying to solve with this
proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular I
don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance
to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the
protocol/struct/enum/class declaration then it implements the methods and
is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement
all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the
output Int are not extended with P2. However as the Int goes into f it
gains P2 conformance and when it leaves it looses P2 conformance. Thus
inside and outside the module the behaviour is easily understood and
consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions. There
is some excellent advice https://blogs.msdn.microsoft.
com/vbteam/2007/03/10/extension-methods-best-
practices-extension-methods-part-6/ written by the VB .NET team when
they added extensions to VB .NET. The best-practice advice can be
summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is
formalised in the proposal by limiting final extensions to be fileprivate
or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions." Translation
to Swift terminology provide default implementations for protocol methods.
The proposal encourages this by eliminating a major gotcha with the current
implementation, namely the proposal always dispatches via a Vtable to give
consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between a
protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon < >>>>>> brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If
it is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

@Goffredo,

"but while the core team has always stated "how else do we share code
between structs/value types?" The proposal provides a way to do this safely

  -- Howard.

···

On 3 May 2017 at 17:33, Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 08:25, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I definitely agree that it's a feature that _can_ be used unwisely, but
the fact remains that it _is_ used pervasively in the standard library, and
deliberately, and that such uses have gone through Swift Evolution and been
approved.

I think there is still sense in discussing it if we care about the
language. I do agree that it is more likely and pragmatic (than removing it
outright) to have a warning about it that people can turn on and treat as
an error if they so choose, but while the core team has always stated "how
else do we share code between structs/value types?" essentially, I am not
sure why this should be allowed by default on class/reference types.
To me it just does not make sense and it is a dangerous compromise we have
and a regression from Objective-C.

So there is really no point in discussing the removal of the feature, as
it simply cannot happen.
On Wed, May 3, 2017 at 02:01 Goffredo Marocchi <panajev@gmail.com> wrote:

Sent from my iPhone

On 3 May 2017, at 01:44, Xiaodi Wu via swift-evolution < >> swift-evolution@swift.org> wrote:

I don't understand your response. The standard library distinguishes
between protocol requirements with default implementations, which can be
overridden, and protocol extension methods, which can only be shadowed but
not overridden. It is used pervasively, from integers to collections. For
example, you can shadow but not override Sequence.contains. This is a
deliberate design choice. You are describing this as "undesirable";
however, it is not only highly desired (as expressed by many on this list
every time a proposal to change it has come up), it would be impossible to
maintain the current design of the standard library without this
distinction.

Being able to forbid overriding is fine, allowing shadowing without a
compiler warning/error is undesirable though. We should not have to dig up
80's discussions about polymorphism to see that changing the actual code
being executed by casting a reference one way or the other is wrong. It may
be instrumentally good for some odd reason to someone, but I cannot see it
as intrinsically good.

Shadowing a method in a class declared in a protocol extension, where it
also receives its default implementation, means that casting the instance
of the class to the class type or the protocol type would have different
methods being executed which can easily lead to mistakes beyond just
appearing confusing and wrong.

(let alone that IMHO protocols/interfaces are meant to decouple code and
API contract and by definition shouldn't really have code in them, but it
is convenient for us as we need to share code between value types...).

In your new design, how would you express a protocol which has some
requirements that have default implementations which can be overridden and
some implemented methods that cannot be overridden? If the answer is that
you cannot do that, then there is a problem.
On Tue, May 2, 2017 at 18:55 Howard Lovatt <howard.lovatt@gmail.com> >> wrote:

You raise three points:

  1. The harm is the inconsistent behaviour of extensions for both
structs and classes, as outlined in the first section of the proposal. This
is confusing for beginners and difficult to debug in large code bases,
particularly those involving third party libraries were source is not
available. I think a lot of the current experience with Swift does not use
large code bases or third party libraries because the experience is with
App development. As Swift moves to the server side large code bases and
third party libraries will become the norm and the problems that result
from the inconsistent behaviour will be magnified.

  2. I am not saying that the current inconsistent behaviour is a bug I
am saying it is undesirable. The Generics Manifesto also lists the
behaviour as undesirable. Changes can and should be made for undesirable
behaviour, e.g. the exclusivity proposal currently under review and the
scoping of private which has been approved already.

  3. I don't think making the changes required would be that large and
the payoff of enabling large code bases and third party libraries is huge.
The changes would involve:

    i. Moving some extensions from a seperate file into the file were
the type was declared. This is good practice anyway and consistent with the
behaviour of private, so no big deal. You should be doing this anyway. This
would hardly affect the standard library.

    ii. Removing declarations from protocols that have implementations
in extensions to *that* protocol. Easily caught by the compiler and Xcode
could do the refactoring.

    ii. Marking retrospective conformance via extensions with final.
Because this also means that the methods need to be final there could be
some change. However, I would argue change for the good since it clarifies
what happens, much like the changes needed for exclusivity are good. Note
that since enum and struct methods are already final there is no change
here other than adding final. Again a small change that the compiler/Xcode
can do. The only area likely to have any issues are retrospective
conformance for protocols and classes. This is a small price to pay for
something as valuable as using third party libraries.

-- Howard.

On 2 May 2017, at 6:33 pm, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

I'm sorry, it's been a while. What is the harm that you are trying to
cure, and how does this design accomplish that task?

What you call "unexpected" is intentional. Many protocols, including the
revised integer protocols that were just approved, distinguish between
protocol requirements for which default implementations are provided and
protocol extension methods which can be shadowed but not overridden. Both
are used, and deliberately. Are you proposing to remove this feature? That
simply cannot be done, as it would require re-designing vast amounts of the
standard library that were just re-designed.

On Tue, May 2, 2017 at 02:54 Howard Lovatt <howard.lovatt@gmail.com> >>> wrote:

I haven't replied to these messages for a while since it has taken some
time to formulate a proposal that incorporates the feedback give - thanks
for the feedback.

The new proposal allows retroactively added protocols to be exported
and ad-hoc code reuse, the two areas of concern.

Comments?

============================================================

# Proposal: Split extension into implementing methods and adding
methods and protocols retrospectively

## Revision history

> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance to
a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |
> Draft 4 | 2 May 2017 | Allow final extensions to be public and
allow ad-hoc code reuse |

## Introduction

Currently extension methods are confusing because they have different
dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

The situation with classes is even more confusing:

    class C: P { /*gets the protocol extensions*/ }
    let pC: P = C()
    pC.mP() // P.mP as expected!
    pC.mE() // P.mE as expected!
    class D: C {
        /*override not allowed!*/ func mP() -> String { return "D.mP" }
        /*override not allowed!*/ func mE() -> String { return "D.mE" }
    }
    let pD: P = D()
    pD.mP() // P.mP unexpected!
    pD.mE() // P.mE unexpected!

This proposal cures the above two problem by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively. The proposal still retains
retroactively adding protocol conformance and ad-hoc code reuse, however
these are made easy to understand and safe.

## Implementing methods in same file as type declaration

If the extension is in the **same** file as the type declaration then
its implemented methods are dispatched using a Vtable for protocols and
classes and statically for structs and enums. EG:

File P.swift

    protocol P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type **and** in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access, can
be final, and can have where clauses and provide inheritable
implementations. Ad-hoc code reuse is supported, in particular if a
class/enum/strict already had a method, m say, and a protocol, P say,
required an m then an extension that added P would not need to provide m
(i.e. as at present).

In a protocol at present you can declare a method that is then
implemented in an extension without the use of the override keyword. This
situation only applies to protocols, for structs/enumerated/classes you
cannot declare in type and implement in an extension at all. This proposal
unifies the behaviour of protocol/struct/enum/class with extensions and
also prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error, by requiring either:

  1. The method is only declared in the protocol and not in any
extensions and is therefore abstract
  2. The method is only in one extension and not in the protocol

A method can be abstract in one protocol and implemented in a second
protocol that extends the first.

The implementation needed to achieve this proposal for a protocol is
that a value instance typed as a protocol is copied onto the heap, a
pointer to its Vtable added, and its address passed/copied (i.e. it becomes
a class instance). No change is needed for a class instance typed as a
protocol, which unlike at present can now be passed/copied as a protocol
directly. Think of a protocol as like an abstract class; cannot be
instantiated like an abstract class and which possibly has abstract
methods, but in different in that it cannot have fields but can be multiply
inherited.

Static and final methods implemented in extensions are not part of the
Vtable and are statically dispatched, i.e. no change from current Swift for
static but final now has the expected meaning for a protocol. Dispatching
for structs and classes unchanged.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a `final extension`, which can be
either in or outside the file in which the protocol/struct/enum/class
declaration is in:

File P.swift

    protocol P {}
    extension P {
        func m() { print("P.m") } // m is added to the protocol
declaration
    }

Same or another file

    struct S: P {} // Inherits m from the extension

In file P2.swift

    protocol P2 {
        func m2()
        func m() // Note same signature as P.m which S already
implements
    }

In same or another file

    final extension S: P2 { // Note extension marked final
        // m cannot be provided because S already has a final m (the
inherited method must be final)
        func m2() { print("SP2.m2") } // Implicitly final, completes
implementation of P2
        func mE() { print("SP2.mE") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S() // or S() as P2 or s: P2
    s.m() // Prints S.m
    s.m2() // Prints SP2.m2
    s.mE() // Prints SP2.mE

Notes:

  1. A method added by a `final extension`, e.g. `mE`, is implicitly
final (as the name would suggest).

  2. If the `final extension` adds a method, e.g. `mE`, that method
cannot already exist. IE a `final extension` cannot override an existing
method or implement a protocol declared method that lacks an implementation
(unless it also adds the protocol). This is retroactively adding a method.
Also see next point.

  3. If the `final extension` adds a protocol, e.g. `P2`, then it must
implement all the methods in that protocol that are not implemented, e.g.
`m2`. This is retroactively adding protocol conformance. Also see next
point.

  4. If the `final extension` adds a protocol, e.g. `P2`, then it
inherits all the methods in that protocol that are implemented, e.g. `m`.
These inherited methods must be final. This is ad-hoc code reuse of final
methods when retroactively adding protocol conformance.

Final-extensions can have `where` clauses.

The implementation for a `final extension` is always static
dispatching. That is why all methods involved in a `final extension` are
final. The compiler always knows that the method can be called statically
and there is no need for a Vtable entry for any of the methods, it is as
though the methods were declared static but with the more convenient syntax
of a normal method.

## Justification

The aim of Swift is nothing more than dominating the world. Using the
current, April 2017, TIOBE Index - TIOBE index of job
adverts for programmers the languages that are in demand are: Java 15.568%,
C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual Basic
.NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl 2.413%,
Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well for a
new language and is already above Objective-C at 14th. However there is
obviously a long way to go and the purpose of this proposal is to help with
this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular, the two forms of
extensions in this proposal can safely be exported.

As part of Swift's goal of world domination is that it is meant to be
easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages. The
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. It
is this keeping it small and simple test that extensions have failed in
other languages, in particular their behaviour is hard to predict in a
large code base with multiple third party libraries.

However, extensions are popular in Swift and this proposals makes a few
changes to them to make their behaviour predictable both in terms of third
party libraries and in terms of method dispatch when the variable is typed
as a protocol. Thereby still providing extensions including retroactive
conformance and ad-hoc code reuse, but without the problems.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add symmetry
to where declarations and bodies may appear for protocols.

## In summary

The proposal formalises the split use of extensions into their two
uses: implementing methods and retroactively adding protocols and methods
(in both cases including ad-hoc code reuse). The purpose of this split is
to eliminate the problems associated with exceptions that have been well
documented both with respect to Swift and other languages. Syntax is added
that clarifies their two use cases (implementing methods and retroactively
adding):

  1. The former are termed extensions and must be in the same file as
the type is declared, but can have non-final or final methods.
  2. The latter are termed final-extensions and can be in any file,
however final-extensions only have final methods.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in <
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md>.

============================================================

On Sun, 23 Apr 2017 at 6:36 am, Thorsten Seitz <tseitz42@icloud.com> >>>> wrote:

+1

Extensions are a great feature and I’m really glad that Swift has
them. Conflicts should be handled by improving import and disambiguation
features like Xiaodi says which is useful for other cases as well.

-Thorsten

Am 18.04.2017 um 03:47 schrieb Xiaodi Wu via swift-evolution < >>>>> swift-evolution@swift.org>:

Simple: you put the user code that needs the more accurate library in
one file and import only the more accurate library there, and you put the
user code that needs the more performant library in a separate file and
import only the more performant library there! Swift's devotion to
file-based organization presents endless avenues of flexibility!

What you write is an argument for designing a more expressive import
and/or disambiguation feature, not for disallowing public retroactive
conformance. A proposal to rip out entirely the ability to vend public APIs
with extensions is simply not going to fly. The core team has committed to
a small standard library and multiple independent core libraries like
Foundation. This can only work because Foundation can greatly expand the
API of standard library types through extensions.

Your proposal would undo that design decision and require folding
Foundation's functionality into the standard library, or rewriting the
entire Foundation overlay to encapsulate standard library types instead of
extending them. For example, NSString would have to be a separate type that
encapsulates String. Yet oodles of work have gone into making NSString
seamlessly bridge to String in the first place.
On Mon, Apr 17, 2017 at 20:05 Howard Lovatt <howard.lovatt@gmail.com> >>>>> wrote:

Comments in-line below

-- Howard.

On 17 Apr 2017, at 9:01 am, Xiaodi Wu <xiaodi.wu@gmail.com> wrote:

This continues to forbid use cases that are critical.

I think "critical" is overstating the importance. Plenty of
successful languages do not have extensions. Extensions have been discussed
and rejected by successful languages. The .NET guidelines suggest
considered cautious use. I have tried to encapsulate the best practice into
a language feature.

For instance, I am writing a library that vends additional
conformances for Float and Double. Any numerics library would need to do
the same.

You need to consider this carefully because your numerics library
might add a method sinh for example and the user of your library might be
using other numerical libraries as well, one of these others might also
provide sinh. Which is to be called in the user code by f.sinh? Suppose one
library emphasises speed over accuracy and the other vice versa. You really
want access to both versions in the user code. This is a situation I have
come across a few times in numeric C, Java, and C++ with matrix libraries
where code I have worked on has used multiple libraries in the same
application for good reason.

I think you would be better vending functions for things like sinh,
rather than extending float with an additional function, and vending types
for more complex things like matrices, rather than extending arrays with
dot products for example. If you vend a type you can easily give access to
the underlying type using composition rather than extension or inheritance,
there is an example of this in the proposal just above the Justification
section..

Your design would eliminate all such libraries, which is a
non-starter. I am not sure what defects you are trying to solve with this
proposal.

I am trying to make Swift more consistent, easier to learn, and to
encourage third-party libraries.

On Sun, Apr 16, 2017 at 17:51 Howard Lovatt <howard.lovatt@gmail.com> >>>>>> wrote:

@Brent,

I have updated the proposal to address your concerns, in particular
I don't see that retrospectively adding methods and protocols has been
removed it has just had its ugly corners rounded. See revised proposal
below particularly the end of section "Retrospectively adding
protocols and methods" and new section "Justification".

Hope this convinces you that the change is worthwhile.

-- Howard.

====================================

# Proposal: Split extension usage up into implementing methods and
adding methods and protocols retrospectively

## Revision history
> Version | Date | Comment |
>---------|--------------|--------------|
> Draft 1 | 11 April 2017 | Initial version |
> Draft 2 | 13 April 2017 | Added support for post-hoc conformance
to a protocol - replaced static final extensions with final extensions |
> Draft 3 | 17 April 2017 | Added justification section |

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols retrospectively.

## Implementing methods

If the extension is in the same file as the
protocol/struct/enum/class declaration then it implements the methods and
is dispatched using a Vtable. EG:

File P.swift
    protocol/struct/enum/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/enum/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for
structs/enumerated/classes you cannot declare in type and implement in
extensions. The proposal unifies the behaviour of
protocol/struct/enum/class with extensions and prevents the error of a
minor typo between the protocol and extension adding two methods instead of
generating an error.

The implementation needed to achieve this proposal is that a value
instance typed as a protocol is copied onto the heap, a pointer to its
Vtable added, and it is passed as a pointer. IE it becomes a class
instance. No change needed for a class instance typed as a protocol.

## Retrospectively adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/enum/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

Notes:

  1. If the final extension adds a method, e.g. m2E, that method
cannot already exist. IE a final extension cannot override an existing
method or implement a protocol declared method that lacks an implementation
unless it also adds the protocol.

  2. If the final extension adds a protocol then it must implement
all the methods in that protocol that are not currently implemented.

  3. If the final extension is outside of the file in which the
protocol/struct/enum/class declaration is in then the extension and the
methods can only have fileprivate or internal access. This prevents
retrospective extensions from numerous modules clashing, since they are not
exported outside of the module.

When a type is extended inside a module with a final extension the
extension is not exported. For example:

    final extension Int: P2 {
        func m2P() { print("Int.m2P") }
    }

If an exported function uses Int, e.g.:

    public func f(_ x: Int) -> Int {
        x.m2P()
        return x
    }

Then when used in an external module both the input Int and the
output Int are not extended with P2. However as the Int goes into f it
gains P2 conformance and when it leaves it looses P2 conformance. Thus
inside and outside the module the behaviour is easily understood and
consistent and doesn't clash with other final extensions in other modules.

Taking the above example further an Int with P2 conformance is
required by the user of a library; then it can simply and safely be
provided, e.g.:

    public class P2Int: P2 {
        var value = 0
        func m2P() { print("Int.m2P") }
    }

This type, P2Int, is easy to write, one line longer than a final
extension, and can easily be used as both a P2 and an Int and does not
clash with another Int extension from another module.

## Justification

The aim of Swift is nothing more than dominating the world. Using
the current, April 2017, TIOBE Index - TIOBE index
of job adverts for programmers the languages that are in demand are: Java
15.568%, C 6.966%, C++ 4.554%, C# 3.579%, Python 3.457%, PHP 3.376%, Visual
Basic .NET 3.251%, JavaScript 2.851%, Delphi/Object Pascal 2.816%, Perl
2.413%, Ruby 2.310%, and Swift 2.287%. So Swift at 12th is doing very well
for a new language and is already above Objective-C at 14th. However there
is obviously a long way to go and the purpose of this proposal is to help
with this climb.

A characteristic of many of the languages above Swift in the Tiobe
Index is that they have major third party libraries; for some languages
they are almost defined by their third part libraries, e.g. Ruby for Rails.
A major part of this proposal is to make extensions safe when using
multiple libraries from different venders. In particular final extensions
are not exported.

As part of Swift's goal of world domination is that it is meant to
be easy to learn by a process of "successive disclosure". The current
inconsistent behaviour of protocols and extensions hinders this process and
is a common gotcha for newbies. This proposal eliminates that problem also.

Extensions are not new in languages, they are part of the .NET
languages for example. Since .NET popularised extensions they have been
discussed by other language communities, particularly Java and Scala, and
in the academic community (normally termed the Expression Problem) however
they have not proved popular because of the problems they cause. Nearly all
languages have a strong bias towards keeping the language small and simple
and trade of the advantages of a feature against the disadvantages and the
feature only makes it into the language if it offers many advantages, has
few disadvantages, and is not heavily overlapping with other features. This
keeping it small and simple test is what extensions have failed in other
languages.

Experience from .NET can however be used to improve extensions.
There is some excellent advice https://blogs.msdn.microsoft.
com/vbteam/2007/03/10/extension-methods-best-
practices-extension-methods-part-6/ written by the VB .NET team
when they added extensions to VB .NET. The best-practice advice can be
summarised by the following quotes from the reference:

  0. "In most real world applications these suggestions [the rest of
the suggestions] can (and quite frankly should!) be completely ignored."
This is an important observations, in your own code that is not intended
for reuse; go for it, use extensions. The proposal importantly still allows
this style of programming and in fact improves it by adding consistent
behaviour and syntax between protocols/structs/enumerated/classes.

1. "Read the .NET Framework Class Library Design Guidelines." The
equivalent for Swift is lacking at this stage. Probably because third party
libraries are rare.

  2. "Be wary of extension methods." This recommendation is
formalised in the proposal by limiting final extensions to be fileprivate
or internal.

  3. "Put extension methods into their own namespace." This
recommendation is formalised in the proposal by limiting final extensions
to be fileprivate or internal.

  4. "Think twice before extending types you don’t own."

  5. "Prefer interface extensions over class extensions."
Translation to Swift terminology provide default implementations for
protocol methods. The proposal encourages this by eliminating a major
gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

  6. "Be as specific with the types you extend as possible."
Translation to Swift terminology provide default implementations for
protocol methods that extend other protocols if there is a more specific
behaviour that is relevent. The proposal encourages this by eliminating a
major gotcha with the current implementation, namely the proposal always
dispatches via a Vtable to give consistent behaviour.

The proposal formalises these best practices from .NET whilst
increasing consistence and without loosing the ability to use extensions
heavily in your own one-off code to allow for rapid development. Most of
the best practices are for better libraries, particularly third party,
which is an important area for future Swift growth onto the server side.
This proposal actively encourages this transition to large formal server
side code without loosing the free wheeling nature of app code.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

===================================================

#Proposal: Split extension usage up into implementing methods and
adding methods and protocols post-hoc

Draft 2 (Added support for post-hoc conformance to a protocol -
replaced static final extensions with final extensions)

## Introduction

Currently extension methods are confusing because they have
different dispatch rules for the same calling syntax. EG:

    public protocol P {
        func mP() -> String
     }
    extension P {
        func mP() -> String { return "P.mP" }
        func mE() -> String { return "P.mE" }
    }
    struct S: P {
        func mP() -> String { return "S.mP" }
        func mE() -> String { return "S.mE" }
    }
    let s = S()
    s.mP() // S.mP as expected
    s.mE() // S.mE as expected
    let p: P = s // Note: s now typed as P
    p.mP() // S.mP as expected
    p.mE() // P.mE unexpected!

Extension methods can also cause compatibility problems between
modules, consider:

In Module A
    extension Int: P {
        func m() -> String { print("A.m") }
    }

In Module B
    extension Int: P {
        func m() -> String { print("B.m") }
    }

In Module C
    import A
    import B // Should this be an error
    let i = 0
    i.m() // Should it return A.m or B.m?

This proposal cures the above two problems by separating extension
methods into two seperate use cases: implementations for methods and adding
methods and protocols post-hoc.

## Implementing methods

If the extension is in the same file as the protocol/struct/class
declaration then it implements the methods and is dispatched using a
Vtable. EG:

File P.swift
    protocol/struct/class P {
        // func m() not declared in type since it is added by the
extension, under this proposal it is an error to include a declaration in a
type *and* in an extension
    }
    extension P {
        func m() { print("P.m") } // m is added to the
protocol/struct/class declaration
    }

Same or other file
    struct S: P {
        override func m() { print("S.m") } // Note override required
because m already has an implementation from the extension
    }
    let p: P = S() // Note typed as P
    p.m() // Now prints S.m as expected

Extensions in the same file as the declaration can have any access,
can be final, and can have where clauses and provide inheritable
implementations.

In a protocol at present there is a difference in behaviour between
a protocol that declares a method that is then implemented in an extension
and a protocol that just has the method implemented in an extension and no
declaration. This situation only applies to protocols, for structs and
classes you cannot declare in type and implement in extensions. The
proposal unifies the behaviour of protocol/struct/class with extensions and
prevents the error of a minor typo between the protocol and extension
adding two methods instead of generating an error.

The implementation needed to achieve this is that a value instance
typed as a protocol is copied onto the heap, a pointer to its Vtable added,
and it is passed as a pointer. IE it becomes a class instance. No change
needed for a class instance typed as a protocol.

## Post-hoc adding protocols and methods

A new type of extension is proposed, a "final extension", which can
be either in or outside the file in which the protocol/struct/class
declaration is in. EG:

    protocol P2 {
        func m2P()
    }
    final extension S: P2 { // Note extension marked final
        func m2P() { print("SP2.m2P") } // Implicitly final,
completely implements P2
        func m2E() { print("SP2.m2E") } // Implicitly final, not an
existing method
    }

Which are called as any other method would be called:

    let s = S()
    s.m2P() // Prints SP2.m2P
    s.m2E() // Prints SP2.m2E

A method added by a final extension is is implicitly final, as the
name would suggest, and cannot be overridden.

If the final extension:

  1. Adds a method, e.g. m2E, that method cannot already exist. IE a
final extension cannot override an existing method or implement a protocol
declared method that lacks an implementation unless it also post-hoc adds
the protocol.

  2. Adds a protocol then it must implement all the methods in that
protocol that are not currently implemented.

  3. Is outside of the file in which the protocol/struct/class
declaration is in then the extension and the methods can only have
fileprivate or internal access. This prevents post-hoc extensions from
numerous modules clashing, since they are not exported outside of the
module.

## Possible future work (not part of this proposal)

This proposal will naturally allow bodies to be added to protocols
directly rather than via an extension, since under the proposal the
extension adds the declaration to the type so it is a small step to allow
the protocol methods to have an implementation.

In an opposite sense to the above adding bodies to protocols,
extensions could be allowed to add method declarations without bodies to
protocols.

The two above future work proposals, if both added, would add
symmetry to where declarations and bodies may appear for protocols.

## In summary.

The proposal formalises the split use of extensions into their two
uses: implementing methods and post-hoc adding protocols and methods.
Syntax is added that clarifies the two use cases, the former are termed
extensions and must be in the same file as the type is declared, and the
latter are termed final extensions and can be in any file, however if they
are not in the type's file the they can only have fileprivate or internal
access.

Note the distinction between an extension in the same file and in a
separate file is consistent with the philosophy that there is special
status to the same file as proposed for private in
GitHub - apple/swift-evolution: This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.
proposals/0169-improve-interaction-between-private-
declarations-and-extensions.md.

====================================

On 14 Apr 2017, at 8:17 am, Brent Royal-Gordon < >>>>>>> brent@architechies.com> wrote:

On Apr 13, 2017, at 3:10 PM, Howard Lovatt via swift-evolution < >>>>>>> swift-evolution@swift.org> wrote:

I don't see that retroactive conformance needs to be exportable. If
it is exported then you cannot prevent clashes from two modules, this is a
known problem in C#. Because of this and other problems with C# extensions,
this style of extension were rejected by other language communities
(notably Java and Scala).

A better alternative for export is a new class that encapsulates the
standard type but with added methods for the protocol to be added. This way
there is no clash between modules. EG:

   public protocol P {

       func m() -> String

   }

   public class PInt: P {

       var value = 0

       func m() -> String { return "PI.m" }

   }

Howard, this would be very source-breaking and would fail to achieve
fundamental goals of Swift's protocol design. Removing retroactive
conformance is no more realistic than removing Objective-C bridging—another
feature which introduces various ugly edge cases and tricky behaviors but
is also non-negotiable.

--
Brent Royal-Gordon
Architechies

_______________________________________________

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

--

-- Howard.

_______________________________________________

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