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-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to