[swift-dev] How should NSArray<void(^)(void)>* be imported?

Joe Groff jgroff at apple.com
Tue Mar 8 15:26:08 CST 2016


> On Mar 5, 2016, at 1:54 AM, Jacob Bandes-Storch <jtbandes at gmail.com> wrote:
> 
> I'm wading through little by little, but I clearly still have a lot to learn... sorry if I'm bothering you with questions!
> 
> Comparing the SIL for the `completionBlock` getter, which is imported as ()->()...
> 
>      %15 = class_method [volatile] %14 : $NSOperation, #NSOperation.completionBlock!getter.1.foreign : NSOperation -> () -> (() -> ())? , $@convention(objc_method) (NSOperation) -> @autoreleased Optional<@convention(block) () -> ()>
> 
>     Here I see that "@convention(block)" is retained in the type information, and appears in the expanded form Optional<@convention(block) ()->()>, even though the getter completionBlock getter is of type "NSOperation -> () -> (() -> ())?", and ()->() is what we see in generated interfaces.
> 
> ...vs. the `executionBlocks` getter, which is imported as [()->()]...
> 
>      %11 = class_method [volatile] %10 : $NSBlockOperation, #NSBlockOperation.executionBlocks!getter.1.foreign : NSBlockOperation -> () -> [() -> ()] , $@convention(objc_method) (NSBlockOperation) -> @autoreleased Optional<NSArray>
>      %12 = apply %11(%10) : $@convention(objc_method) (NSBlockOperation) -> @autoreleased Optional<NSArray>
>      %13 = function_ref @_TF10Foundation22_convertNSArrayToArrayurFGSqCSo7NSArray_GSax_ : $@convention(thin) <τ_0_0> (@owned Optional<NSArray>) -> @owned Array<τ_0_0>
>      %14 = apply %13<() -> ()>(%12) : $@convention(thin) <τ_0_0> (@owned Optional<NSArray>) -> @owned Array<τ_0_0>
>      release_value %14 : $Array<() -> ()>
> 
> I don't see @convention(block) anywhere here. And when I check the type of static_cast<FunctionTypeMetadata*>(T)->getConvention(), from inside findBridgeWitness, the convention is Swift.
> 
> So not only is there no conformance for blocks (which seems like an easy thing to add, like you said, similarly to _BridgeableMetatype), but I think the @convention(block) is being completely lost by adjustTypeForConcreteImport. Is this true or am I missing something?
> 
> How is @convention(block) retained after importing in order to produce the right type from completionBlock.getter, namely Optional<@convention(block) ()->()>, but it appears only as Optional<()->()> in the generated interface? Why does this mechanism not produce a call to _convertNSArrayToArray<@convention(block) ()->()>,  but only _convertNSArrayToArray<()->()> ?

I think this is a problem at the Clang importer level. It's probably assuming that if you have a parameter of type NSArray<T> in Objective-C, and T is bridgeable to BT, then it should always be imported as Array<BT> (and SILGen would be able to insert the conversions during code generation). If you want to preserve the block-ness, it may need a special case at that level.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160308/fe9f231a/attachment.html>


More information about the swift-dev mailing list