> On Jun 13, 2017, at 7:32 PM, Jordan Rose <jordan_r...@apple.com> wrote: >> On Jun 13, 2017, at 16:11, John McCall via swift-dev <swift-dev@swift.org >> <mailto:swift-dev@swift.org>> wrote: >> >> 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. >> >> A bridging conversion is a conversion between a Swift type and a foreign >> type (C / ObjC / whatever) which can represent the same set of values. For >> example, there are bridging conversions from Swift.String to ObjC's NSString >> and vice-versa. When there two-way conversions like this, we say that the >> Swift type is bridged to the foreign type. >> >> Bridging conversions are performed for three reasons in Swift: >> >> 1. You can always request a bridging conversion with an unconditional "as" >> cast. For example, if myString is a String, you can convert it to NSString >> by writing "myString as NSString". >> >> 2. Certain bridging conversions can be introduced as implicit conversions. >> (This is perhaps a mistake.) For example, CFString and NSString are >> considered different types, but they will implicitly convert to each other. >> >> 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. 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. >> >> Bridging conversions are not always desirable. First, they do impose some >> performance overhead which the user may not want. But they can also change >> semantics in unwanted ways. 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. A pair of >> bridging conversions from NSString to String and then back to NSString is >> likely to lose this reference identity. 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. >> >> 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. This is >> unsatisfactory. 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. We do not >> want optimization settings to be able to affect things as important as >> whether a particular NSString is mutable or not. >> >> The proposal is to apply a guaranteed syntactic "peephole" to eliminate >> bridging conversions that arise from reason #3. Specifically: >> >> No bridging conversions will be performed if: >> - a call, property reference, or subscript reference is the immediate >> syntactic >> operand of an "as" cast to a type compatible with the foreign return, >> property, >> or subscript element type or >> - a call argument, right operand of an assignment to a property >> reference, or >> right operand of an assignment to a subscript reference is an "as" >> cast from a >> type compatible with the foreign parameter, property, or subscript >> element type. >> Two types are "compatible" if there is a simple subclass or class-protocol >> relationship >> between the underlying non-optional types. >> >> We believe that this rule is easy and intuitive enough to understand that it >> will not cause substantial problems. > > Thanks for writing this all down, John. Should returns also be included in > this? That is: > > override func someObjCFunction() -> String { > return NSMutableString() as String > }
Hmm. 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. Maybe we can find a way to promise that later? Or maybe we could just allow such overrides to use the foreign types instead of the native ones. > (and, having written that, it seems useful to show code examples for each of > your cases.) Sure. This would avoid the bridging conversions through [View] on the return value of the getter: let subviews = view.subviews as NSArray This would not: let subviews = view.subviews let nsSubviews = subviews as NSArray This would avoid the bridging conversion through [CIFilter] on the argument to the setter: view.backgroundFilters = nsFilters as [CIFilter] This would not: let filters = nsFilters as [CIFilter] view.backgroundFilters = filters John.
_______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev