> On Mar 23, 2016, at 1:25 PM, Russ Bishop <[email protected]> wrote:
> 
> 
>> On Mar 23, 2016, at 11:49 AM, Douglas Gregor <[email protected] 
>> <mailto:[email protected]>> wrote:
>>> 
>>> I assume this is a static function to avoid allocating memory by calling 
>>> the initializer directly for each element, given the point is to defer the 
>>> work? I wonder if we can skip the static though and just call the 
>>> initializer directly? It would simplify the protocol a tiny bit.
>> 
>> From an implementation perspective, the entry point for an initializer in a 
>> protocol handles the allocation itself. It’s a static function because it 
>> was easy to implement that way and the actual definitions get a bit more 
>> flexibility in how they can come up with the object (since we don’t have 
>> factory initializers).
>  
> Good point about the factory initializers. I’ve been trying to keep the whole 
> “class cluster” situation in mind. I wonder if there should be an equivalent 
> static function for the conditional bridging for similar reasons?

I realize that my comment about factory initializers was a bit off: these are 
initializers on the value type, so there are no “class clusters” to be had. 
Sorry for the noise!

> I added a separate section on Ambiguity and what the behavior is. I think you 
> should be able to resolve ambiguity by casting so I went ahead and put that 
> in. An example:
> 
> //Bar and Foo bridge to SomeObjectiveCType
> struct Bar<T>: ObjectiveCBridgeable { }
> struct Foo<T>: ObjectiveCBridgeable { }
> 
> class API {
>     let foo: Foo<Int>
>     func objCVersionOfAFunction(obj: SomeObjectiveCType) -> 
> SomeObjectiveCType {
>         let x = obj as! Bar<Int>
>         // We've told the compiler which protocol impl to call
>         return foo as! SomeObjectiveCType
>     }
> }
> 
> Any problems with this approach? It makes handling the ambiguous or manual 
> bridging case relatively straightforward, though there may be objections to 
> using casting this way. [Be careful, I still mourn the loss of @conversion so 
> I’m biased :)]


The problem I have with allowing the ambiguity is that you can get weird 
behavior if Bar and Foo are in different modules: import just Bar’s module, and 
an Objective-C API mentioning SomeObjectiveCType gets bridged as a Bar. Import 
just Foo’s module, and an Objective-C API mentioning SomeObjectiveCType gets 
bridged as a Foo. Import both, and SomeObjectiveCType doesn’t get bridged! Now 
start splitting class hierarchies among those modules and you get some very 
inconsistent imports… that’s why I think this needs to be an error.

> 
> 
> `NSInteger` is already imported as `Int` from Objective-C right? I assume a 
> Clang attribute is specifying that somewhere but there wouldn’t be any 
> ambiguity on the Swift side during import.

It’s hardcoded, but it’s completely reasonable to imagine swift_bridge doing 
this some day.

> I could definitely see having an attribute to declare that this specific 
> parameter or return value should bridge to a specific Swift type (this 
> NSNumber should import as Int) but that’s a lot of work and may be worth a 
> separate proposal.

It would be hard for me to get motivated for such a proposal; at that point, 
just wrap up the API.

> It seems like the problem is going the other direction: you want to 
> materialize this parameter or whatever as `NSInteger` instead of the default 
> `NSNumber *` but only when directly bridged, not inside collections. There’s 
> no existing Objective-C header to tell us what to do. I’m not sure how we can 
> resolve this without a Swift attribute to tell the compiler because the 
> handling of it would be specific to each declaration. 

I don’t have a good answer here; today, it’s hardcoded.

> We could just  say that we aren’t going to let people have that level of 
> granularity. Then just introduce a BuiltInBridgeable protocol that supersedes 
> ObjectiveCBridgeable. A type adopting both will cause the compiler to prefer 
> the built-in protocol when generating a bridging header, but the collection 
> types can ignore that and just use ObjectiveCBridgeable. Presumably the 
> BuiltInBridgeable protocol would just have an associated type to indicate 
> that the bits are directly mapped to BuiltIn.Word or whatever.

Yes, that’s a reasonable approach. I don’t think it’s important for this 
proposal.

Two last comments came up, then I’d like to merge and schedule this:

(1) isBridgedToObjectiveC should be a computed property, not a function

(2) Please add something indicating that, while one can “as” cast between a 
value type and its bridged Objective-C type, there are no implicit conversions. 
We currently have implicit conversions from String -> NSString, Array<T> -> 
NSArray, Dictionary<K, V> -> NSDictionary, and Set<T> -> NSSet, but we’re not 
happy about them and we don’t want to create more implicit conversions [*].

        - Doug

[*] The fact that you mourn the loss of @conversion did not go unnoticed as I 
was writing this ;)


_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to