Environment
|
|
| skip (Skip.git) |
1.9.7 (26808ac3604663a73ad79cbacccb287d6a3957d4) |
| Xcode |
26.4.1 (17E202) |
| Toolchain for the Android SDK build |
swift-6.2.3-RELEASE.xctoolchain (chosen by Skip itself, --swift-sdk aarch64-unknown-linux-android28) |
| Affected paths |
skip android test --apk and the instrumented XCSkipTests path (ANDROID_SERIAL → connectedDebugAndroidTest) |
| Project |
Swift Package Manager multiplatform app using Skip Fuse |
Description
Both test execution paths generate a temporary test harness
(.../T/<uuid>/harness/Sources/TestHarness/TestRunner.swift), whose line 154 fails to compile
under Swift 6 strict concurrency:
152 | let semaphore = DispatchSemaphore(value: 0)
153 | nonisolated(unsafe) var testSuccess = false
154 | Task {
| |- error: sending value of non-Sendable type '() async -> ()' risks causing data races [#SendingRisksDataRace]
| `- note: Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code
155 | defer { semaphore.signal() }
156 | do {
:
162 | semaphore.wait()
163 |
164 | let exitCode: Int32 = testSuccess ? 0 : 1
| `- note: access can happen concurrently
165 | return jint(exitCode)
166 | }
TestRunner.swift is generated by Skip itself — there is no way to influence the generated
harness via project or compiler flags. -Xswiftc -swift-version -Xswiftc 5 in our own
Package.swift does not reach this build, because Skip builds the harness in its own temporary
package with its own flags.
Before upgrading to Skip 1.9.7, a separate Kotlin generator defect (Unresolved reference 'Bundle') masked the instrumented path — that defect is fixed as of this upgrade, and
TestRunner.swift:154 is now the same visible blocker on both paths.
Reproduction
1. skip android test --apk log
[0/1] Planning build
[1/1] Compiling plugin Create SkipLink
[2/2] Compiling plugin skipstone
Building for debugging...
[2/16] Write swift-version--35B2706C3EC7C88B.txt
Build complete! (8.89s)
[✓] Check Swift Package (0.64s)
Building for debugging...
[0/5] Write sources
[1/5] Write swift-version--35B2706C3EC7C88B.txt
error: emit-module command failed with exit code 1 (use -v to see invocation)
[3/7] Emitting module TestHarness
/private/var/.../T/7CC6111F-E935-4B29-97B8-E0DC8A7641EC/harness/Sources/TestHarness/TestRunner.swift:154:5: error: sending value of non-Sendable type '() async -> ()' risks causing data races [#SendingRisksDataRace]
152 | let semaphore = DispatchSemaphore(value: 0)
153 | nonisolated(unsafe) var testSuccess = false
154 | Task {
| |- error: sending value of non-Sendable type '() async -> ()' risks causing data races [#SendingRisksDataRace]
| `- note: Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code
155 | defer { semaphore.signal() }
156 | do {
:
162 | semaphore.wait()
163 |
164 | let exitCode: Int32 = testSuccess ? 0 : 1
| `- note: access can happen concurrently
165 | return jint(exitCode)
166 | }
[#SendingRisksDataRace]: <https://docs.swift.org/compiler/documentation/diagnostics/sending-risks-data-race>
Error: Error terminated(code: 1) running command: ~/Library/Developer/Toolchains/swift-6.2.3-RELEASE.xctoolchain/usr/bin/swift build --swift-sdk aarch64-unknown-linux-android28 --package-path .../harness --configuration debug
2. Instrumented XCSkipTests / connectedDebugAndroidTest log
[2/2] Compiling plugin skipstone
Building for debugging...
[2/18] Write swift-version--35B2706C3EC7C88B.txt
Build complete! (5.13s)
[✓] Check Swift Package (0.15s)
Building for debugging...
[0/5] Write sources
[1/5] Write swift-version--35B2706C3EC7C88B.txt
error: emit-module .../checkouts/skip/Sources/SkipTest/XCGradleHarness.swift:356: error: -[XCSkipTests testSkipModule] : error: emit-module command failed with exit code 1 (use -v to see invocation)
.../checkouts/skip/Sources/SkipTest/XCGradleHarness.swift:356: error: -[XCSkipTests testSkipModule] : Execution failed for task ':buildAndroidSwiftTestLibs' (registered in build file 'build.gradle.kts').
.../plugins/outputs/.../SkipTestHarness/XCSkipTests.swift:10: error: -[XCSkipTests testSkipModule] : failed - The expected test output folder did not exist, which may indicate that the gradle process encountered a build error or other issue.
Test Case '-[XCSkipTests testSkipModule]' failed (30.856 seconds).
[3/7] Emitting module TestHarness
.../T/80D22003-B19A-4C60-B411-D6A62A705B1A/harness/Sources/TestHarness/TestRunner.swift:154:5: error: sending value of non-Sendable type '() async -> ()' risks causing data races [#SendingRisksDataRace]
152 | let semaphore = DispatchSemaphore(value: 0)
153 | nonisolated(unsafe) var testSuccess = false
154 | Task {
| |- error: sending value of non-Sendable type '() async -> ()' risks causing data races [#SendingRisksDataRace]
| `- note: Passing value of non-Sendable type '() async -> ()' as a 'sending' argument to initializer 'init(name:priority:operation:)' risks causing races in between local and caller code
155 | defer { semaphore.signal() }
156 | do {
:
162 | semaphore.wait()
163 |
164 | let exitCode: Int32 = testSuccess ? 0 : 1
| `- note: access can happen concurrently
165 | return jint(exitCode)
166 | }
[#SendingRisksDataRace]: <https://docs.swift.org/compiler/documentation/diagnostics/sending-risks-data-race>
Error: Error terminated(code: 1) running command: ~/Library/Developer/Toolchains/swift-6.2.3-RELEASE.xctoolchain/usr/bin/swift build --package-path .../harness --configuration debug --swift-sdk aarch64-unknown-linux-android28 --build-system native
FAILURE: Build failed with an exception.
Both logs show the same failing line in the generated TestRunner.swift:154.
Expected vs. Actual
- Expected: The generated test harness compiles under Swift 6 strict concurrency.
- Actual:
emit-module aborts with #SendingRisksDataRace, blocking both test paths.
Impact
Without a fix, the instrumented Android test lane (with a real Looper / main-thread
semantics) is unreachable, which blocks automated verification of @MainActor/main-thread
behavior that today can only be checked via manual screenshots. The regular skip android test
lane (non-instrumented) is not affected — it uses a different path.
Environment
1.9.7(26808ac3604663a73ad79cbacccb287d6a3957d4)swift-6.2.3-RELEASE.xctoolchain(chosen by Skip itself,--swift-sdk aarch64-unknown-linux-android28)skip android test --apkand the instrumentedXCSkipTestspath (ANDROID_SERIAL→connectedDebugAndroidTest)Description
Both test execution paths generate a temporary test harness
(
.../T/<uuid>/harness/Sources/TestHarness/TestRunner.swift), whose line 154 fails to compileunder Swift 6 strict concurrency:
TestRunner.swiftis generated by Skip itself — there is no way to influence the generatedharness via project or compiler flags.
-Xswiftc -swift-version -Xswiftc 5in our ownPackage.swiftdoes not reach this build, because Skip builds the harness in its own temporarypackage with its own flags.
Before upgrading to Skip
1.9.7, a separate Kotlin generator defect (Unresolved reference 'Bundle') masked the instrumented path — that defect is fixed as of this upgrade, andTestRunner.swift:154is now the same visible blocker on both paths.Reproduction
1.
skip android test --apklog2. Instrumented
XCSkipTests/connectedDebugAndroidTestlogBoth logs show the same failing line in the generated
TestRunner.swift:154.Expected vs. Actual
emit-moduleaborts with#SendingRisksDataRace, blocking both test paths.Impact
Without a fix, the instrumented Android test lane (with a real Looper / main-thread
semantics) is unreachable, which blocks automated verification of
@MainActor/main-threadbehavior that today can only be checked via manual screenshots. The regular
skip android testlane (non-instrumented) is not affected — it uses a different path.