<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><blockquote type="cite" class=""><div class="">On Jun 13, 2017, at 7:32 PM, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class=""><div class="">On Jun 13, 2017, at 16:11, John McCall via swift-dev &lt;<a href="mailto:swift-dev@swift.org" class="">swift-dev@swift.org</a>&gt; 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="">So, there's a longstanding issue that we're planning to fix in Swift 4, and I want to both make sure that the plan is documented publicly and give people a chance to disagree with it.<div class=""><br class=""></div><div class="">A <b class="">bridging conversion</b>&nbsp;is a conversion between a Swift type and a foreign type (C / ObjC / whatever) which can represent the same set of values. &nbsp;For example, there are bridging conversions from Swift.String to ObjC's NSString and vice-versa. &nbsp;When there two-way conversions like this, we say that the Swift type is<b class=""> bridged to</b> the foreign type.</div><div class=""><br class=""></div><div class="">Bridging conversions are performed for three reasons in Swift:</div><div class=""><br class=""></div><div class="">1. You can always request a bridging conversion with an unconditional "as" cast. &nbsp;For example, if myString is a String, you can convert it to NSString by writing "myString as NSString".</div><div class=""><br class=""></div><div class="">2. Certain bridging conversions can be introduced as implicit conversions. &nbsp;(This is perhaps a mistake.) &nbsp; For example, CFString and NSString are considered different types, but they will implicitly convert to each other.</div><div class=""><br class=""></div><div class="">3. Bridging conversions are done "behind the scenes" when using an imported declaration that has been given a type that does not match its original type. &nbsp;For example, an Objective-C method that returns an NSString will be imported as returning a String; Swift will implicitly apply a bridging conversion to the true return value in order to produce the String that the type system has promised.</div><div class=""><br class=""></div><div class="">Bridging conversions are not always desirable. &nbsp;First, they do impose some performance overhead which the user may not want. &nbsp;But they can also change semantics in unwanted ways. &nbsp;For example, in certain rare situations, the reference identity of an NSString return value is important — maybe it's actually a persistent NSMutableString which should be modified in-place, or maybe it's a subclass which carries additional information. &nbsp;A pair of bridging conversions from NSString to String and then back to NSString is likely to lose this reference identity. &nbsp;In the current representation, String can store an NSString reference, and if the String is bridged to NSString that reference will be used as the result; however, the bridging conversion from NSString does not directly store the original NSString in the String, but instead stores the result of invoking +copy on it, in an effort to protect against the original NSString being somehow mutable.</div><div class=""><br class=""></div><div class="">Bridging conversions arising from reasons #1 and #2 are avoidable, but bridging conversions arising from reason #3 currently cannot be eliminated without major inconvenience, such as writing a stub in Objective-C. &nbsp;This is unsatisfactory. &nbsp;At the same time, it is not valid for Swift to simply eliminate pairs of bridging conversions as a matter of course, precisely because those bridging conversions can be semantically important. &nbsp;We do not want optimization settings to be able to affect things as important as whether a particular NSString is mutable or not.</div><div class=""><br class=""></div><div class="">The proposal is to apply a guaranteed syntactic "peephole" to eliminate bridging conversions that arise from reason #3. &nbsp;Specifically:</div><div class=""><br class=""></div><div class="">&nbsp; No bridging conversions will be performed if:</div><div class="">&nbsp; &nbsp; - a call, property reference, or subscript reference is the immediate syntactic</div><div class="">&nbsp; &nbsp; &nbsp; operand of an "as" cast <i class="">to</i> a type compatible with the foreign return, property,</div><div class="">&nbsp; &nbsp; &nbsp; or subscript element type or</div><div class="">&nbsp; &nbsp; - a call argument, right operand of an assignment to a property reference, or</div><div class="">&nbsp; &nbsp; &nbsp; right operand of an assignment to a subscript reference is an "as" cast <i class="">from</i>&nbsp;a</div><div class="">&nbsp; &nbsp; &nbsp; type compatible with the foreign parameter, property, or subscript element type.</div><div class="">&nbsp; Two types are "compatible" if there is a simple subclass or class-protocol relationship</div><div class="">&nbsp; between the underlying non-optional types.</div><div class=""><br class=""></div><div class="">We believe that this rule is easy and intuitive enough to understand that it will not cause substantial problems.</div></div></div></blockquote><br class=""></div><div class="">Thanks for writing this all down, John. Should returns also be included in this? That is:</div><div class=""><br class=""></div><div class="">override func someObjCFunction() -&gt; String {</div><div class="">&nbsp; return NSMutableString() as String</div><div class="">}</div></div></div></blockquote><div><br class=""></div>Hmm. &nbsp;We're not in a position to make this guarantee easily, because this isn't inherently a foreign method in the same way that an imported API is. &nbsp;Maybe we can find a way to promise that later? &nbsp;Or maybe we could just allow such overrides to use the foreign types instead of the native ones.</div><div><br class=""></div><div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">(and, having written that, it seems useful to show code examples for each of your cases.)</div></div></div></blockquote><div><br class=""></div></div>Sure.<div class=""><div class=""><br class=""></div><div class="">This would avoid the bridging conversions through [View] on the return value of the getter:</div><div class="">&nbsp; let subviews = view.subviews as NSArray</div><div class=""><br class=""></div><div class="">This would not:</div><div class="">&nbsp; let subviews = view.subviews</div><div class="">&nbsp; let nsSubviews = subviews as NSArray</div><div class=""><br class=""></div><div class="">This would avoid the bridging conversion through [CIFilter] on the argument to the setter:</div><div class="">&nbsp; view.backgroundFilters = nsFilters as [CIFilter]</div><div class=""><br class=""></div><div class="">This would not:</div><div class="">&nbsp; let filters = nsFilters as [CIFilter]</div><div class="">&nbsp; view.backgroundFilters = filters</div><div class=""><br class=""></div><div class="">John.</div><div class=""><br class=""></div></div></body></html>