[Swift] Fail to load executable when extending DispatchQueue with protocol

Originator:zach
Number:rdar://26850367 Date Originated:16-Jun-2016 04:38 PM
Status:Closed Resolved:true
Product:Developer Tools Product Version:Xcode Version 8.0 beta (8S128d)
Classification:Other Bug Reproducible:Always
 
Summary:
In adapting a GCD-oriented framework for Swift 3, it becomes possible to extend `DispatchQueue` to conform to a protocol, whereas this was not possible when `dispatch_queue_t` was an opaque class type.

Unfortunately, actually doing the conformance causes a runtime dylib linking failure.

Steps to Reproduce:
1. Create a framework using the "Framework & Library -> Cocoa Touch Framework" template, with the "Include Unit Tests" box checked.
2. Add a protocol with methods to the framework as a public member.
3. Import `Dispatch` and make `DispatchQueue` implement the protocol.
4. Attempt to run the tests.

Expected Results:
Empty test bundle having linked the framework runs successfully.

Actual Results:
Tests fail without any notes in the debug log or Test logs (see attached). The Tests item in the Report navigator reads: "Test target DeferredTests encountered an error (Early unexpected exit, operation never finished bootstrapping - no restart will be attempted)".

If code coverage is enabled, Xcode presents the rather cryptic dialog "Code Coverage Data Generation Failed - Unable to retrieve the profile data files from 'My Mac'."

Version:
Xcode Version 8.0 beta (8S128d)
OS X El Capitan 10.11.6 Beta (15G12a)

Notes:
In the system console log, the following helpful bits are left behind:
6/16/16 4:33:33.744 PM xctest[26546]: The bundle “DeferredTests” couldn’t be loaded. Try reinstalling the bundle.
6/16/16 4:33:33.744 PM xctest[26546]: (dlopen(/.../DerivedData/Deferred/Build/Intermediates/CodeCoverage/Products/Debug/DeferredTests.xctest/Contents/MacOS/DeferredTests, 265): Symbol not found: _OBJC_CLASS_$_OS_dispatch_queue
  Referenced from: /.../DerivedData/Deferred/Build/Intermediates/CodeCoverage/Products/Debug/Deferred.framework/Versions/A/Deferred
  Expected in: /usr/lib/libSystem.B.dylib
 in /.../DerivedData/Deferred/Build/Intermediates/CodeCoverage/Products/Debug/Deferred.framework/Versions/A/Deferred)




Configuration:


Attachments:
'MiniDeferred.zip' and 'Session-DeferredTests-2016-06-16_163317-OJyju9.log' were successfully uploaded.

Comments

https://github.com/apple/swift/commit/7d1a2e8339c0d83a1143698e0f90ad020dfeb1b2 notes that only @objc members of extensions are forbidden based on the objc_runtime_visible rules, so this would appear to be a legitimate bug. (Fingers crossed.)

I performed some further investigation. The load failure doesn't occur on a 10.12 target; it's trivially reproducible in an app target running on 10.11 from Swift 3 with the 10.12 SDK.

The protocol conformance witness table hard-emits a reference to the OS_dispatch_queue class, which was only available at runtime on previous OS'. All other normal uses of the class route through objc_lookUpClass based on the objc_runtime_visible Clang attribute.

Sample project: https://bucket.waldowski.me/26850367-MiniDeferred


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!