<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">When you call foo<A : P>(_: A) with a concrete type C, the type checker performs a conformance check of C to P. If C is a protocol type, the conformance check fails. Ie, unlike the subtype relation (roughly, “I can assign a value of this type to that”), the conformance relation (“I can substitute this for a generic parameter conforming to”) is not reflexive.</div><div class=""><br class=""></div><div class="">Swift compiles generic code in a way where values of generic type have the most efficient representation in memory — you pay a CPU cost because they’re still manipulated indirectly (unlike C++ templates, which are cloned and inlined at compile time), but there’s no representational cost as in Java’s erased generics for example.</div><div class=""><br class=""></div><div class="">What this means is that all types that you can substitute for a generic parameter have to be interchangeable in some basic sense.</div><div class=""><br class=""></div><div class="">The main problem is with class-bound protocols:</div><div class=""><br class=""></div><div class="">protocol CP : class {</div><div class=""> func foo()</div><div class=""> func bar()</div><div class="">}</div><div class=""><br class=""></div><div class="">And a function taking an array of CP’s:</div><div class=""><br class=""></div><div class="">func foo<T : CP>(t: [T]) {}</div><div class=""><br class=""></div><div class="">All concrete types that conform to a class-bound protocol have a single retainable-pointer representation, so the function takes an array of pointers.</div><div class=""><br class=""></div><div class="">However, a value of protocol type ‘CP’ is represented as the underlying concrete value — a pointer to a class instance conforming to CP — together with the conformance table that stores the function pointers for the implementations of ‘foo’ and ‘bar’.</div><div class=""><br class=""></div><div class="">So unlike in Java, where method implementations for an interface are stored “inside” the instance, in Swift protocol requirement implementations are always passed ‘on the side’.</div><div class=""><br class=""></div><div class="">With opaque protocols, a type parameter has variable size, so there’s no representational issue. Instead you just get a double indirection.</div><div class=""><br class=""></div><div class="">Say you have</div><div class=""><br class=""></div><div class="">protocol P {}</div><div class="">func foo<T : P>(t: [T]) {}</div><div class=""><br class=""></div><div class="">If you call foo with the substitution P := P, then you’re passing in an array of values *where each value has its own conformance to P*. But foo() itself wants the conformance P : P. So when you call a protocol requirement on an element of ’t’. you will first call a method in the ‘dummy’ conformance P : P, which will unpack the “real” concrete type from the value of type P and call the right method on that.</div><div class=""><br class=""></div><div class="">So we could implement self-conformance for non-class-bound protocols. For class-bound protocols, I’m not sure how to do it efficiently.</div><div class=""><br class=""></div><div class="">Slava</div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 30, 2016, at 8:26 AM, Mikhail Seriukov <<a href="mailto:zloisop@gmail.com" class="">zloisop@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">So as the <span style="font-size:12.8px" class=""><b class="">foo<A:P>(_ x:A) </b>function is generic, when we call <b class="">foo(x) </b>compiler needs to determine what type is <b class="">A </b>to be able to create concrete function. But x defined as <b class="">let x = X() as P </b>so we only know about it that it conforms to <b class="">P </b>but not its real type to put instead of <b class="">A</b>. Right?<br class="">But where is the "</span><span style="font-size:12.8px" class="">Protocols do not conform to themselves</span><span style="font-size:12.8px" class="">" limitation is coming out?</span></div><div class="gmail_extra"><br class=""><div class="gmail_quote">2016-12-30 18:25 GMT+07:00 Rien <span dir="ltr" class=""><<a href="mailto:Rien@balancingrock.nl" target="_blank" class="">Rien@balancingrock.nl</a>></span>:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br class="">
> On 30 Dec 2016, at 12:14, Mikhail Seriukov via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class="">
><br class="">
> Ok,<br class="">
> But I think I still do not get it.<br class="">
> What does really happen when we write this?<br class="">
>> let x = X() as P<br class="">
>><br class="">
<br class="">
</span>'X()' creates a value.<br class="">
'as P’ constrains the value such that the only things we know about it is that the value will conform to the protocol P<br class="">
‘let x =‘ assigns the value to a constant, and the only thing we know about that constant is that we can call an operation of protocol P on it.<br class="">
<span class="HOEnZb"><font color="#888888" class=""><br class="">
Rien.<br class="">
</font></span><div class="HOEnZb"><div class="h5"><br class="">
> As I said, I expect x to be Any<P> after that. If it is, then it should be ok IMO.<br class="">
> But if it is not then what is the actual type of x?<br class="">
><br class="">
> So the real question is how the type checker works here?<br class="">
><br class="">
><br class="">
> 2016-12-25 22:13 GMT+07:00 Slava Pestov <<a href="mailto:spestov@apple.com" class="">spestov@apple.com</a>>:<br class="">
><br class="">
>> On Dec 22, 2016, at 4:43 PM, Howard Lovatt via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class="">
>><br class="">
>> The following variation works:<br class="">
>><br class="">
>> protocol P {}<br class="">
>><br class="">
>> class P1:P {}<br class="">
>><br class="">
>> class X:P1 {}<br class="">
>><br class="">
>> func foo<A:P>(_ x:A) {}<br class="">
>><br class="">
>> func bar() {<br class="">
>> //let x = X() // this compiles<br class="">
>> let x = X() as P1 // this does not compile. Why?<br class="">
>> foo(x)<br class="">
>> }<br class="">
>><br class="">
>> Which adds credence to the bug theory.<br class="">
><br class="">
> It’s an intentional limitation. Protocols do not conform to themselves. Lifting the restriction would be difficult to do efficiently given our representation of generics and protocols at runtime.<br class="">
><br class="">
> Slava<br class="">
><br class="">
>><br class="">
>> Note two changes: 1. two levels of inheritance and 2. change to classes. If you do two levels using protocols it doesn't work if you use either classes or structs.<br class="">
>><br class="">
>><br class="">
>> -- Howard.<br class="">
>><br class="">
>> On 23 December 2016 at 07:29, Kevin Nattinger <<a href="mailto:swift@nattinger.net" class="">swift@nattinger.net</a>> wrote:<br class="">
>> I recall seeing a request on the -evolution list for something like `T := X` to indicate it could be X itself or anything inheriting / implementing it, so it’s certainly known behavior, if not desired. IMO it’s a bug and `:` should be fixed to include the root type, whether or not that requires a discussion on -evolution.<br class="">
>><br class="">
>>> On Dec 22, 2016, at 2:17 PM, Howard Lovatt via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class="">
>>><br class="">
>>> I suspect a compiler bug since A is a P. The equivalent in Java works:<br class="">
>>><br class="">
>>> interface P {}<br class="">
>>> class X implements P {}<br class="">
>>><br class="">
>>> <A extends P> void foo(A x) {}<br class="">
>>><br class="">
>>> void bar() {<br class="">
>>> final P x = new X();<br class="">
>>> foo(x);<br class="">
>>> }<br class="">
>>><br class="">
>>> -- Howard.<br class="">
>>><br class="">
>>> On 23 Dec 2016, at 3:19 am, Rien via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class="">
>>><br class="">
>>>> IMO the error message says it all:<br class="">
>>>><br class="">
>>>> Playground execution failed: error: MyPlayground8.playground:9:5: error: cannot invoke 'foo' with an argument list of type '(P)'<br class="">
>>>> foo(x)<br class="">
>>>> ^<br class="">
>>>><br class="">
>>>> MyPlayground8.playground:9:5: note: expected an argument list of type '(A)'<br class="">
>>>> foo(x)<br class="">
>>>> ^<br class="">
>>>><br class="">
>>>> I.e. you are passing in a protocol while the function is specified for a type.<br class="">
>>>> Said other way: On which data do you expect the protocol to operate?<br class="">
>>>><br class="">
>>>> Regards,<br class="">
>>>> Rien<br class="">
>>>><br class="">
>>>> Site: <a href="http://balancingrock.nl/" rel="noreferrer" target="_blank" class="">http://balancingrock.nl</a><br class="">
>>>> Blog: <a href="http://swiftrien.blogspot.com/" rel="noreferrer" target="_blank" class="">http://swiftrien.blogspot.com</a><br class="">
>>>> Github: <a href="http://github.com/Swiftrien" rel="noreferrer" target="_blank" class="">http://github.com/Swiftrien</a><br class="">
>>>> Project: <a href="http://swiftfire.nl/" rel="noreferrer" target="_blank" class="">http://swiftfire.nl</a><br class="">
>>>><br class="">
>>>><br class="">
>>>><br class="">
>>>><br class="">
>>>>> On 22 Dec 2016, at 17:05, Mikhail Seriukov via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:<br class="">
>>>>><br class="">
>>>>> Hello community! I' wondering if somebody can explain this to me.<br class="">
>>>>> Please take look at the snippet.<br class="">
>>>>><br class="">
>>>>> protocol P {}<br class="">
>>>>> struct X:P {}<br class="">
>>>>><br class="">
>>>>> func foo<A:P>(_ x:A) {}<br class="">
>>>>><br class="">
>>>>> func bar() {<br class="">
>>>>> //let x = X() // this compiles<br class="">
>>>>> let x = X() as P // this does not compile. Why?<br class="">
>>>>> foo(x)<br class="">
>>>>> }<br class="">
>>>>><br class="">
>>>>> I expect the both cases to work though. But only first works? And I do not understand why.<br class="">
>>>>> My coworkers said that it is a compiler bug, but I'm not shure it is.<br class="">
>>>>> Thanks for the help.<br class="">
>>>>> ______________________________<wbr class="">_________________<br class="">
>>>>> swift-users mailing list<br class="">
>>>>> <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
>>>>> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
>>>><br class="">
>>>> ______________________________<wbr class="">_________________<br class="">
>>>> swift-users mailing list<br class="">
>>>> <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
>>>> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
>>> ______________________________<wbr class="">_________________<br class="">
>>> swift-users mailing list<br class="">
>>> <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
>>> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
>><br class="">
>><br class="">
>> ______________________________<wbr class="">_________________<br class="">
>> swift-users mailing list<br class="">
>> <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
>> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
><br class="">
><br class="">
> ______________________________<wbr class="">_________________<br class="">
> swift-users mailing list<br class="">
> <a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a><br class="">
> <a href="https://lists.swift.org/mailman/listinfo/swift-users" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-users</a><br class="">
<br class="">
</div></div></blockquote></div><br class=""></div>
</div></blockquote></div><br class=""></body></html>