<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Mar 2, 2016, at 8:26 PM, Douglas Gregor <<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 2, 2016, at 5:38 PM, Joe Groff <<a href="mailto:jgroff@apple.com" class="">jgroff@apple.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Mar 2, 2016, at 5:22 PM, Douglas Gregor via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div class=""><span class="" style="font-size: 14px;"><i class="">Private conformances </i></span></div><div class=""><br class=""></div><div class="">Right now, a protocol conformance can be no less visible than the minimum of the conforming type’s access and the protocol’s access. Therefore, a public type conforming to a public protocol must provide the conformance publicly. One could imagine removing that restriction, so that one could introduce a private conformance:</div></div><div class=""><br class=""></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><font face="Menlo" class="">public protocol P { }</font></div><div class=""><font face="Menlo" class="">public struct X { }</font></div></div><div class=""><div class=""><font face="Menlo" class="">extension X :<span class="Apple-converted-space"> </span><b class="">internal P</b><span class="Apple-converted-space"> </span>{ … } // X conforms to P, but only within this module</font></div></div></blockquote><div class=""><div class=""><br class=""></div><div class="">The main problem with private conformances is the interaction with dynamic casting. If I have this code:</div><div class=""><br class=""></div></div><blockquote class="" style="margin: 0px 0px 0px 40px; border: none; padding: 0px;"><div class=""><div class=""><font face="Menlo" class="">func foo(value: Any) {</font></div></div><div class=""><div class=""><font face="Menlo" class=""> if let x = value as? P { print(“P”) }</font></div></div><div class=""><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><div class=""><font face="Menlo" class="">foo(X())</font></div></div></blockquote><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Under what circumstances should it print “P”? If foo() is defined within the same module as the conformance of X to P? If the call is defined within the same module as the conformance of X to P? Never? Either of the first two answers requires significant complications in the dynamic casting infrastructure to take into account the module in which a particular dynamic cast occurred (the first option) or where an existential was formed (the second option), while the third answer breaks the link between the static and dynamic type systems—none of which is an acceptable result.</div></div></div></blockquote></div><br class=""><div class="">You don't need private conformances to introduce these coherence problems with dynamic casting. You only need two modules that independently extend a common type to conform to a common protocol. As Jordan discussed in his resilience manifesto, a publicly-subclassable base class that adopts a new protocol has the potential to create a conflicting conformance with external subclasses that may have already adopted that protocol. </div></div></div></blockquote><div class=""><br class=""></div><div class="">Right, multiple conformances do happen in our current model. Personally, I think that the occurrence of multiple conformances should effectively be an error at runtime unless the conformances are effectively identical (same type witnesses with the same conformances may be a reasonable approximation), and even then it’s worthy of a diagnostic as early as we can produce one, because the amount of infrastructure one needs to handle multiple conformances is significant.</div></div></div></div></blockquote><div><br class=""></div><div>If it's a runtime error, that's a huge resilience liability, since any library adding a conformance would potentially be causing its users to start crashing at load time.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">This seems to me like poor grounds for rejecting the ability to have private conformances. I think they're a really useful feature.</div></div></div></blockquote><br class=""></div><div class="">With what semantics? Truly embracing private and multiple conformances means embedding it in type identity:</div><div class=""><br class=""></div><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;" class=""><div class=""><font face="Menlo" class="">// Module A</font></div><div class=""><font face="Menlo" class="">public protocol P {</font></div><div class=""><font face="Menlo" class=""> associatedtype A</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class="">public struct X<T : P> { }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// Module B</font></div><div class=""><font face="Menlo" class="">struct Y { }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// Module C</font></div><div class=""><font face="Menlo" class="">import A</font></div><div class=""><font face="Menlo" class="">import B</font></div><div class=""><font face="Menlo" class="">extension Y : private P {</font></div><div class=""><font face="Menlo" class=""> typealias A = Int</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">public func f() -> Any { return X<Y>() }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// Module D</font></div><div class=""><div class=""><font face="Menlo" class="">import A</font></div></div><div class=""><div class=""><font face="Menlo" class="">import B</font></div></div><div class=""><div class=""><font face="Menlo" class="">extension Y : private P {</font></div><div class=""><font face="Menlo" class=""> typealias A = Double</font></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><div class=""><font face="Menlo" class=""><br class=""></font></div></div><div class=""><font face="Menlo" class="">public func g(x: Any) {</font></div><div class=""><font face="Menlo" class=""> if let y = x as? X<Y> { /* do we get here? */ }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// Module E</font></div><div class=""><font face="Menlo" class="">import A</font></div><div class=""><div class=""><font face="Menlo" class="">import B</font></div><div class=""><div class=""><font face="Menlo" class="">import C</font></div></div><div class=""><div class=""><font face="Menlo" class="">import D</font></div></div><div class=""><font face="Menlo" class="">g(f())</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div></div></blockquote><div class="">It’s not that we can’t make this behave correctly—the answer is “no”, we don’t get into the “then” block, because modules D and E effectively have different types X<Y> due to the differing conformances—but that making this behave correctly has a nontrivial runtime cost (uniquing via protocol conformances) and can cause major confusion (wait, X<Y> isn’t a single thing?), for what I suspect is a fairly rare occurrence.</div></div></div></blockquote><br class=""></div><div>Yeah, I suspect the overlap of dynamic casting and use cases for private conformances is small, so it seems unfortunate to me to hobble the language around the needs of dynamic casts. A workable rule might be to say that private or internal conformances aren't exposed to runtime lookup, so are never found by as? casts. We could then statically reject the `as? X<Y>` cast here since the X<Y> instantiation depends on a runtime-invisible conformance.</div><div><br class=""></div><div>-Joe</div><br class=""></body></html>