<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 23, 2016, at 11:49 AM, Douglas Gregor <<a href="mailto:dgregor@apple.com" class="">dgregor@apple.com</a>> wrote:</div><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=""><br class=""></div></blockquote><div class=""><br class=""></div><div class="">Great. The suggestion to use an extension won’t actually work:</div><div class=""><br class=""></div></div></div></div></blockquote><div><br class=""></div><div>Doh. Thanks for catching that, I pushed a fix.</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class=""><div class=""> </div></div></div><div class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: 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;" class=""><div class="">I assume this is a static function to avoid allocating memory by calling the initializer directly for each element, given the point is to defer the work? I wonder if we can skip the static though and just call the initializer directly? It would simplify the protocol a tiny bit.</div></div></div></blockquote><div class=""><br class=""></div><div class="">From an implementation perspective, the entry point for an initializer in a protocol handles the allocation itself. It’s a static function because it was easy to implement that way and the actual definitions get a bit more flexibility in how they can come up with the object (since we don’t have factory initializers).</div></div></div></blockquote><div> </div><div>Good point about the factory initializers. I’ve been trying to keep the whole “class cluster” situation in mind. I wonder if there should be an equivalent static function for the conditional bridging for similar reasons?</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" 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="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: 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;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><div class=""><br class=""></div></div></div></div></blockquote></div></div></blockquote></div><div class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: 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;" class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class=""><div class=""><ol class="" style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; font-size: 16px; background-color: rgb(255, 255, 255);"><li class="" style="box-sizing: border-box;">(This was #5) It is an error for bridging to be ambiguous.</li><li class="" style="box-sizing: border-box;"><ol class="" style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 0px; list-style-type: lower-roman;"><li class="" style="box-sizing: border-box;">A Swift type may bridge to an Objective-C base class, then provide different subclass instances at runtime but no other Swift type may bridge to that base class or any of its subclasses.</li><li class="" style="box-sizing: border-box;">The compiler must emit a diagnostic when it detects two Swift types attempting to bridge to the same <code class="" style="box-sizing: border-box; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 14px; padding: 0.2em 0px; margin: 0px; background-color: rgba(0, 0, 0, 0.0392157); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;">ObjectiveCType</code>.</li></ol></li></ol></div><div class="">This is a tricky area. Currently, Int/Float/Double/Bool/CGFloat/UInt all have _ObjectiveCBridgeable conformances, although those conformances only really kick in at runtime (e.g., when dynamically casting an [AnyObject] or [NSNumber] to [Int] or [Double] with as? or matching a switch case). They would run afoul of this rule. However, this rule does generally make sense: if two Swift types have the same ObjectiveCType, we won’t know how to map an Objective-C API back into Swift. Those numeric types only work because they are trivially mapped between Swift and (Objective-)C; they don’t need to go through the _ObjectiveCBridgeable conformance. </div></div></div></blockquote><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Perhaps the rule should simply be that any Objective-C API imported that has ambiguity is imported as the Objective-C type without automatic bridging support. The compiler can continue to import Int and friends with special magic. Creating an ambiguity just leaves you to resolve the problem manually? The rule would be something like "omitting the SWIFT_BRIDGED() attribute from ObjC //or// multiple Swift types bridging to the same ObjC type" turns off automatic thunk generation but bridged collections will still call the protocol where appropriate.</div></div></div></blockquote><div class=""><br class=""></div><div class="">Yeah. Thinking about it a bit further, I like your rule basically as you’ve stated it, because having two _ObjectiveCBridgeable conformances mapping to the same type is a problem the user should have to resolve. I guess I’m just looking for something small to indicate that a direct mapping of the representation (e.g., NSInteger -> Int) supersedes the _ObjectiveCBridgeable conformance when mapping APIs between Objective-C and Swift.</div><div class=""><br class=""></div></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>I added a separate section on Ambiguity and what the behavior is. I think you should be able to resolve ambiguity by casting so I went ahead and put that in. An example:</div><div><br class=""></div><div><div style="margin: 0px; font-size: 14px; line-height: normal; font-family: Menlo; color: rgb(75, 209, 87);" class=""><div style="margin: 0px; font-size: 11px; line-height: normal; color: rgb(0, 132, 0);" class=""><div style="margin: 0px; line-height: normal;" class="">//Bar and Foo bridge to SomeObjectiveCType</div><div style="margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> Bar<T>: </span>ObjectiveCBridgeable<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { }</span></div><div style="margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> Foo<T>: </span>ObjectiveCBridgeable<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> { }</span></div><div style="margin: 0px; line-height: normal; min-height: 13px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">class</span> API {</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> foo: <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Foo</span><<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>></div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">func</span> objCVersionOfAFunction(obj: <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">SomeObjectiveCType</span>) -> <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">SomeObjectiveCType</span> {</div><div style="margin: 0px; line-height: normal;" class=""> <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">let</span> x = obj <span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span>! <span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">Bar</span><<span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Int</span>></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>// We've told the compiler which protocol impl to call</div><div style="margin: 0px; line-height: normal; color: rgb(79, 129, 135);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span>foo<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">! </span>SomeObjectiveCType</div><div style="margin: 0px; line-height: normal;" class=""> }</div><div style="margin: 0px; line-height: normal;" class="">}</div></div></div></div><div><br class=""></div><div>Any problems with this approach? It makes handling the ambiguous or manual bridging case relatively straightforward, though there may be objections to using casting this way. [Be careful, I still mourn the loss of @conversion so I’m biased :)]</div><div><br class=""></div><div><br class=""></div><div>`NSInteger` is already imported as `Int` from Objective-C right? I assume a Clang attribute is specifying that somewhere but there wouldn’t be any ambiguity on the Swift side during import. I could definitely see having an attribute to declare that this specific parameter or return value should bridge to a specific Swift type (this NSNumber should import as Int) but that’s a lot of work and may be worth a separate proposal.</div><div><br class=""></div><div>It seems like the problem is going the other direction: you want to materialize this parameter or whatever as `NSInteger` instead of the default `NSNumber *` but only when directly bridged, not inside collections. There’s no existing Objective-C header to tell us what to do. I’m not sure how we can resolve this without a Swift attribute to tell the compiler because the handling of it would be specific to each declaration. </div><div><br class=""></div><div>We could just say that we aren’t going to let people have that level of granularity. Then just introduce a BuiltInBridgeable protocol that supersedes ObjectiveCBridgeable. A type adopting both will cause the compiler to prefer the built-in protocol when generating a bridging header, but the collection types can ignore that and just use ObjectiveCBridgeable. Presumably the BuiltInBridgeable protocol would just have an associated type to indicate that the bits are directly mapped to BuiltIn.Word or whatever.</div><div><br class=""></div><div><br class=""></div><br class=""><blockquote type="cite" 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 style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: 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;" class="">An update has been posted to <a href="https://github.com/russbishop/swift-evolution/blob/master/proposals/0000-objectivecbridgeable.md" class="">https://github.com/russbishop/swift-evolution/blob/master/proposals/0000-objectivecbridgeable.md</a></div></blockquote><div class=""><br class=""></div>Thanks!</div><div class=""><br class=""><blockquote type="cite" class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: 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;" class="">Would you prefer if I did / did not add your name to the proposal? I feel guilty taking all the credit.</div></blockquote><br class=""></div><div class="">I don’t have a strong preference. Feel free to add my name if you’d like. I really appreciate your work on driving this proposal forward!</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div class=""><br class=""></div></div></blockquote><br class=""></div><div>Happy to do so!</div><div><br class=""></div><div>Russ</div><br class=""></body></html>