Will existentials ever conform to their protocols?


(Braeden Profile) #1

Hello Swift Community!

I know that I’ve seen this mentioned before, but what with Enhanced Existentials being brought up, I think this is worth mentioning now. What is the plan regarding letting existentials conform to their protocols? Currently, in Swift 3, it is impossible to write code like this:
protocol Updatable
  { func update() }

struct UpdatePool<T: Updatable>
  { /* ... */ }

let heterogenousPool = UpdatePool<Updatable>()
Error on the last line: “Using ‘Updatable’ as a concrete type conforming to protocol ‘Updatable’ is not supported.”

Although my most common use case of this behavior has actually been solved (using ‘AnyObject’ as a concrete type conforming to ‘AnyObject’), I wonder why this can’t be extended to any protocol existential (a field which is about to explode, if we succeed in Enhancing them).

What do you guys think?

—Braeden Hintze


(David Sweeris) #2

+1, but I think there's a compiler limitation preventing it at the moment.

- Dave Sweeris

···

On Jan 17, 2017, at 22:30, Braeden Profile via swift-evolution <swift-evolution@swift.org> wrote:

Hello Swift Community!

I know that I’ve seen this mentioned before, but what with Enhanced Existentials being brought up, I think this is worth mentioning now. What is the plan regarding letting existentials conform to their protocols? Currently, in Swift 3, it is impossible to write code like this:
protocol Updatable
  { func update() }

struct UpdatePool<T: Updatable>
  { /* ... */ }

let heterogenousPool = UpdatePool<Updatable>()
Error on the last line: “Using ‘Updatable’ as a concrete type conforming to protocol ‘Updatable’ is not supported.”

Although my most common use case of this behavior has actually been solved (using ‘AnyObject’ as a concrete type conforming to ‘AnyObject’), I wonder why this can’t be extended to any protocol existential (a field which is about to explode, if we succeed in Enhancing them).

What do you guys think?


(Anton Zhilin) #3

There is also a caveat with static members:

protocol P {
    static func foo()
}

struct S : P {
    static func foo() { }
}

func bar<T: P>(x: T) {
    T.foo()
}

let p = S() as P
bar(p) // P.foo() does not exist


(Slava Pestov) #4

Hello Swift Community!

I know that I’ve seen this mentioned before, but what with Enhanced Existentials being brought up, I think this is worth mentioning now. What is the plan regarding letting existentials conform to their protocols? Currently, in Swift 3, it is impossible to write code like this:
protocol Updatable
  { func update() }

struct UpdatePool<T: Updatable>
  { /* ... */ }

let heterogenousPool = UpdatePool<Updatable>()
Error on the last line: “Using ‘Updatable’ as a concrete type conforming to protocol ‘Updatable’ is not supported.”

Although my most common use case of this behavior has actually been solved (using ‘AnyObject’ as a concrete type conforming to ‘AnyObject’), I wonder why this can’t be extended to any protocol existential (a field which is about to explode, if we succeed in Enhancing them).

What do you guys think?

+1, but I think there's a compiler limitation preventing it at the moment.

See my recent post: https://www.mail-archive.com/swift-users@swift.org/msg03427.html

Slava

···

On Jan 17, 2017, at 9:33 PM, David Sweeris via swift-evolution <swift-evolution@swift.org> wrote:
On Jan 17, 2017, at 22:30, Braeden Profile via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

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


(Slava Pestov) #5

Yes, there’s already logic to detect and diagnose this case in fact (@objc protocols are self-conforming, except when they contain static members or initializers).

Slava

···

On Jan 18, 2017, at 12:10 AM, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

There is also a caveat with static members:

protocol P {
    static func foo()
}

struct S : P {
    static func foo() { }
}

func bar<T: P>(x: T) {
    T.foo()
}

let p = S() as P
bar(p) // P.foo() does not exist
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Joe Groff) #6

Right, part of the language design problem here is that not every protocol type is naturally a model of its protocol. In addition to static members, if you have any "Self" arguments in your method requirements, you wouldn't naturally be able to use those requirements, which expect a specific type modeling the protocol, on the type-erased protocol type. For many protocols, there's an obvious generalization—to compare two Equatables, first check that they're the same type, then call the == on the values of that type; for factory protocols with initializer requirements, there may be a reasonable default implementation type to provide if you ask to construct a P(). We'd want a way to provide that self-conformance if it doesn't fall out naturally from generalizing the protocol requirements.

-Joe

···

On Jan 18, 2017, at 12:10 AM, Anton Zhilin via swift-evolution <swift-evolution@swift.org> wrote:

There is also a caveat with static members:

protocol P {
    static func foo()
}

struct S : P {
    static func foo() { }
}

func bar<T: P>(x: T) {
    T.foo()
}

let p = S() as P
bar(p) // P.foo() does not exist