Passing class protocols to functions accepting AnyObject


(Charles Srstka) #1

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
  print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t: P)'

It seems to me that this ought to have been allowed, since P is declared as being a reference type and thus should have been able to satisfy the function’s requirements.

Is this worthy of writing a language proposal, or would this be considered a bug that should be sent through the radar system instead?

Thanks,
Charles


(Derrick Ho) #2

Does the following expression evaluate to true?

p is AnyObject

If it does then you may have found a bug.

···

On Sun, Dec 4, 2016 at 9:46 PM Charles Srstka via swift-evolution < swift-evolution@swift.org> wrote:

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
        print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t:
P)'

It seems to me that this ought to have been allowed, since P is declared
as being a reference type and thus should have been able to satisfy the
function’s requirements.

Is this worthy of writing a language proposal, or would this be considered
a bug that should be sent through the radar system instead?

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


(Joe Groff) #3

It's a limitation of the current implementation. `AnyObject` is taken as meaning that a conforming type has a representation that consists of a single refcounted pointer. Protocol existentials do not have a single-refcounted representation since the witness table for the conformances must also be carried around, therefore the protocol type does not conform to AnyObject's representation requirement.

-Joe

···

On Dec 4, 2016, at 6:46 PM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
  print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t: P)'

It seems to me that this ought to have been allowed, since P is declared as being a reference type and thus should have been able to satisfy the function’s requirements.

Is this worthy of writing a language proposal, or would this be considered a bug that should be sent through the radar system instead?


(Anders) #4

This is not a bug. Existentials of a protocol do not conform to the protocol. But I have no idea why the protocol conformance has not been implemented for at least protocols without `Self` or associated type requirements though.

Regards,
Anders

···

On 5 Dec 2016, at 3:46 AM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
  print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t: P)'

It seems to me that this ought to have been allowed, since P is declared as being a reference type and thus should have been able to satisfy the function’s requirements.

Is this worthy of writing a language proposal, or would this be considered a bug that should be sent through the radar system instead?

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


(Charles Srstka) #5

Not only does it evaluate to true, the compiler warns me that "'is' test is always true”.

Charles

···

On Dec 4, 2016, at 11:49 PM, Derrick Ho <wh1pch81n@gmail.com> wrote:

Does the following expression evaluate to true?

p is AnyObject

If it does then you may have found a bug.


(Charles Srstka) #6

Is there any way to just say “This function takes any reference type” that will work?

Charles

···

On Dec 5, 2016, at 11:39 AM, Joe Groff <jgroff@apple.com> wrote:

On Dec 4, 2016, at 6:46 PM, Charles Srstka via swift-evolution <swift-evolution@swift.org> wrote:

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
  print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t: P)'

It seems to me that this ought to have been allowed, since P is declared as being a reference type and thus should have been able to satisfy the function’s requirements.

Is this worthy of writing a language proposal, or would this be considered a bug that should be sent through the radar system instead?

It's a limitation of the current implementation. `AnyObject` is taken as meaning that a conforming type has a representation that consists of a single refcounted pointer. Protocol existentials do not have a single-refcounted representation since the witness table for the conformances must also be carried around, therefore the protocol type does not conform to AnyObject's representation requirement.


(Joe Groff) #7

You could take 'AnyObject' as the parameter type instead of as a generic constraint. In the fullness of time, we ought to allow protocol types to be implicitly opened, since the value inside `p` conforms to `AnyObject` even if the type `P` happens not to.

-Joe

···

On Dec 5, 2016, at 10:50 AM, Charles Srstka <cocoadev@charlessoft.com> wrote:

On Dec 5, 2016, at 11:39 AM, Joe Groff <jgroff@apple.com <mailto:jgroff@apple.com>> wrote:

On Dec 4, 2016, at 6:46 PM, Charles Srstka via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

The following currently does not work:

protocol P: class {}
class C: P {}

func foo<T>(t: T) where T: AnyObject {
  print("foo")
}

let p: P = C()

foo(t: p) // error: cannot invoke 'foo' with an argument list of type '(t: P)'

It seems to me that this ought to have been allowed, since P is declared as being a reference type and thus should have been able to satisfy the function’s requirements.

Is this worthy of writing a language proposal, or would this be considered a bug that should be sent through the radar system instead?

It's a limitation of the current implementation. `AnyObject` is taken as meaning that a conforming type has a representation that consists of a single refcounted pointer. Protocol existentials do not have a single-refcounted representation since the witness table for the conformances must also be carried around, therefore the protocol type does not conform to AnyObject's representation requirement.

Is there any way to just say “This function takes any reference type” that will work?