> On Jun 14, 2017, at 2:24 AM, David Hart <[email protected]> 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 <[email protected]
> <mailto:[email protected]>> 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
>> [email protected] <mailto:[email protected]>
>> https://lists.swift.org/mailman/listinfo/swift-dev
>> <https://lists.swift.org/mailman/listinfo/swift-dev>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution