> On Jun 14, 2017, at 2:24 AM, David Hart <davidh...@fastmail.com> wrote: > Very good description. It's always worth re-explaining terms like bridged > conversion to make sure every body is on the same page. But concerning the > rules at the end, I’m not quite sure I understood them all. Please let me > know if I’m correct:
Yes, all of your examples should avoid bridging conversions. John. > > 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 > > protocol FooBar { > func foo() -> NSMutableArray > var bar: NSMutableDictionary { get set } > subscript(_ index: Int) -> NSDecimalNumber { get set } > } > > let foobar: FooBar = ... > foobar.foo() as NSArray > foobar.bar as NSDictionary > foobar[0] as NSNumber > > - 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. > > protocol BarFoo { > func foo(_ array: NSArray) > var bar: NSDictionary { get set } > subscript(_ index: Int) -> NSNumber { get set } > } > > var barfoo: BarFoo = ... > barfoo.foo(NSMutableArray() as NSArray) > barfoo.bar = NSMutableDictionary() as NSDictionary > barfoo[1] = NSDecimalNumber(string: "1.2") as NSNumber > > On 14 Jun 2017, at 01:11, John McCall via swift-dev <swift-...@swift.org > <mailto:swift-...@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. >> >> John. >> _______________________________________________ >> swift-dev mailing list >> swift-...@swift.org <mailto:swift-...@swift.org> >> https://lists.swift.org/mailman/listinfo/swift-dev >> <https://lists.swift.org/mailman/listinfo/swift-dev>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution