[Discussion] Allowing extending existentials


(David Hart) #1

Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.


(Jacob Bandes-Storch) #2

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

···

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution < swift-evolution@swift.org> wrote:

Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the
question is: which should be lifted? P1 & P2 seems like an obvious case.
But what about Any and AnyObject? Is there a design reason that we
shouldn’t allow it?

David.

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


(Slava Pestov) #3

Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

This will make name lookup rather complicated. I’d rather not do it. As Jacob mentions, you can almost simulate it with a constrained extension.

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

These two are by design. In the future, AnyObject will be ‘special’ (basically we want to model it as ‘Any & class’), and not a protocol.

Slava

···

On Feb 21, 2017, at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

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


(David Hart) #4

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

···

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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


(Douglas Gregor) #5

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

... which is

extension P1 where Self: C1 {}

Actually extending semantics (e.g. to extend Any or AnyObject) is a very large project that's out of scope. Without that, this is a small bit of syntactic sugar.

  - Doug

···

Sent from my iPhone

On Feb 21, 2017, at 11:25 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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

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


(Adrian Zubarev) #6

I’d love if we could extend the idea even further. It would be great to be able to extend the typealias type, because it can be a more constrained type (with a where clause).

protocol P {
    associatedtype Q
}
class C {}

typealias CP = C & P where Q == Int

extension CP { … }
This would make a lot of constrained extension vanish.

···

--
Adrian Zubarev
Sent with Airmail

Am 22. Februar 2017 um 08:26:33, David Hart via swift-evolution (swift-evolution@swift.org) schrieb:

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
func foo() {}
}

func bar(x: P1 & P2) {
x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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

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


(David Hart) #7

If we drop the idea of extending Any and AnyObject (which is out of scope), does the fact that what is left is syntactic sugar make it unsuitable for Swift 4? I remember Chris saying syntactic sugar is not the goal for Swift 4, but this syntactic sugar looks really sweet (pun intended).

···

On 22 Feb 2017, at 08:36, Douglas Gregor <dgregor@apple.com> wrote:

Sent from my iPhone

On Feb 21, 2017, at 11:25 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

... which is

extension P1 where Self: C1 {}

Actually extending semantics (e.g. to extend Any or AnyObject) is a very large project that's out of scope. Without that, this is a small bit of syntactic sugar.

  - Doug

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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

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


(Slava Pestov) #8

I’d love if we could extend the idea even further. It would be great to be able to extend the typealias type, because it can be a more constrained type (with a where clause).

protocol P {
    associatedtype Q
}
class C {}

typealias CP = C & P where Q == Int

extension CP { … }
This would make a lot of constrained extension vanish.

Once we have generalized existentials, it should be possible to make something like the above desugar into a constrained extension.

Slava

···

On Feb 21, 2017, at 11:34 PM, Adrian Zubarev via swift-evolution <swift-evolution@swift.org> wrote:

--
Adrian Zubarev
Sent with Airmail

Am 22. Februar 2017 um 08:26:33, David Hart via swift-evolution (swift-evolution@swift.org <mailto:swift-evolution@swift.org>) schrieb:

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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

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

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


(Slava Pestov) #9

If we drop the idea of extending Any and AnyObject (which is out of scope), does the fact that what is left is syntactic sugar make it unsuitable for Swift 4? I remember Chris saying syntactic sugar is not the goal for Swift 4, but this syntactic sugar looks really sweet (pun intended).

It’s unlikely we’ll make it a priority to implement anything like that in the Swift 4 timeframe, but PRs are more than welcome :wink:

Slava

···

On Feb 21, 2017, at 11:42 PM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

On 22 Feb 2017, at 08:36, Douglas Gregor <dgregor@apple.com <mailto:dgregor@apple.com>> wrote:

Sent from my iPhone

On Feb 21, 2017, at 11:25 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yes, but it's not very discoverable. Plus, if the subclass existentials proposal is accepted, it would actually allow us to do:

class C {}
extension C & P1 {}

... which is

extension P1 where Self: C1 {}

Actually extending semantics (e.g. to extend Any or AnyObject) is a very large project that's out of scope. Without that, this is a small bit of syntactic sugar.

  - Doug

On 22 Feb 2017, at 08:06, Jacob Bandes-Storch <jtbandes@gmail.com <mailto:jtbandes@gmail.com>> wrote:

This works today:

protocol P1{}
protocol P2{}

extension P1 where Self: P2 {
    func foo() {}
}

func bar(x: P1 & P2) {
    x.foo()
}

On Tue, Feb 21, 2017 at 10:53 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
Hello list,

Found out yesterday that you can’t extend all existentials in Swift:

protocol P1 {}
extension P1 {}
// works as expected

protocol P2 {}
extension P1 & P2 {}
// error: non-nominal type 'P1 & P2' cannot be extended

extension Any {}
// error: non-nominal type 'Any' cannot be extended

extension AnyObject {}
// error: 'AnyObject' protocol cannot be extended

I’d like to write a proposal to lift some of those restrictions. But the question is: which should be lifted? P1 & P2 seems like an obvious case. But what about Any and AnyObject? Is there a design reason that we shouldn’t allow it?

David.

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

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

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


(Douglas Gregor) #10

Part of the reason that Swift 4 stage 2 doesn’t encourage “pure sugar” proposals is because it saps implementation bandwidth for model-enhancing or model-breaking changes that have much more effect. The actual effect is that we can end up reviewing a bunch of proposals that will not get implemented. Having an actual implementation ready to go prior to review can change that calculus somewhat—that’s why, for example, smallish “pure" standard library proposals are in scope but should have implementations [*].

  - Doug

···

On Feb 21, 2017, at 11:46 PM, Slava Pestov <spestov@apple.com> wrote:

On Feb 21, 2017, at 11:42 PM, David Hart via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

If we drop the idea of extending Any and AnyObject (which is out of scope), does the fact that what is left is syntactic sugar make it unsuitable for Swift 4? I remember Chris saying syntactic sugar is not the goal for Swift 4, but this syntactic sugar looks really sweet (pun intended).

It’s unlikely we’ll make it a priority to implement anything like that in the Swift 4 timeframe, but PRs are more than welcome :wink: