<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 1:25 PM, Russ Bishop <<a href="mailto:xenadu@gmail.com" class="">xenadu@gmail.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 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></div></div></blockquote><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=""><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 class=""> </div><div class="">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></div></div></blockquote><div><br class=""></div><div>I realize that my comment about factory initializers was a bit off: these are initializers on the value type, so there are no “class clusters” to be had. Sorry for the noise!</div><div><br class=""></div><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=""><div class="">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 class=""><br class=""></div><div class=""><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="" class=""> Bar<T>: </span>ObjectiveCBridgeable<span style="" 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="" class=""> Foo<T>: </span>ObjectiveCBridgeable<span style="" 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="" 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="" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">return</span><span style="" class=""> </span>foo<span style="" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #bb2ca2" class="">as</span><span style="" 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 class=""><br class=""></div><div class="">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></div></div></blockquote><div><br class=""></div><div><br class=""></div><div>The problem I have with allowing the ambiguity is that you can get weird behavior if Bar and Foo are in different modules: import just Bar’s module, and an Objective-C API mentioning SomeObjectiveCType gets bridged as a Bar. Import just Foo’s module, and an Objective-C API mentioning SomeObjectiveCType gets bridged as a Foo. Import both, and SomeObjectiveCType doesn’t get bridged! Now start splitting class hierarchies among those modules and you get some very inconsistent imports… that’s why I think this needs to be an error.</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=""><div class=""><br class=""></div><div class=""><br class=""></div><div class="">`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. </div></div></div></div></blockquote><div><br class=""></div><div>It’s hardcoded, but it’s completely reasonable to imagine swift_bridge doing this some day.</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=""><div class="">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></div></div></blockquote><div><br class=""></div><div>It would be hard for me to get motivated for such a proposal; at that point, just wrap up the API.</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=""><div class="">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></div></div></blockquote><div><br class=""></div><div>I don’t have a good answer here; today, it’s hardcoded.</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=""><div class="">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></div></div></blockquote><div><br class=""></div>Yes, that’s a reasonable approach. I don’t think it’s important for this proposal.</div><div><br class=""></div><div>Two last comments came up, then I’d like to merge and schedule this:</div><div><br class=""></div><div>(1) isBridgedToObjectiveC should be a computed property, not a function</div><div><br class=""></div><div>(2) Please add something indicating that, while one can “as” cast between a value type and its bridged Objective-C type, there are no implicit conversions. We currently have implicit conversions from String -> NSString, Array<T> -> NSArray, Dictionary<K, V> -> NSDictionary, and Set<T> -> NSSet, but we’re not happy about them and we don’t want to create more implicit conversions [*].</div><div><br class=""></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>- Doug</div><div><br class=""></div><div>[*] The fact that you mourn the loss of @conversion did not go unnoticed as I was writing this ;)</div><div><br class=""></div><br class=""></body></html>