Description
Description
While working in the ReactiveSwift port of The Composable Architecture, more specifically ensuring Linux support, the swift test
calls started failing on the generated __allTests__FooTests
properties as can be seen below.
Relevant CI run here (from ReactiveCocoa/reactiveswift-composable-architecture#58)
/home/runner/work/reactiveswift-composable-architecture/reactiveswift-composable-architecture/.build/x86_64-unknown-linux-gnu/debug/reactiveswift-composable-architecturePackageTests.derived/ComposableArchitectureTests.swift:227:29: error: cannot convert value of type '[Any]' to expected argument type '[(String, (XCTestCase) -> () -> Void)]'
testCase(StoreTests.__allTests__StoreTests),
^
After some investigation I was able to narrow down the problem to the use of @MainActor
on the test suites, which are used on the "problematic" test suites. I then proceeded to create some minimal examples that replicate the issue.
As they are, the following error is triggered:
Heterogeneous collection literal could only be inferred to '[Any]'; add explicit type annotation if this is intentional
Insert ' as [Any]'
If we uncomment the commented lines, the collection literal is correctly inferred to type [(String, (DummyTests) -> @MainActor () throws -> ())]
, but even then I'm not sure if it will work as the expected type appears to be[(String, (XCTestCase) -> () throws -> Void)]
which doesn't have @MainActor
, right?
That means perhaps this means @MainActor
is simply not supported yet as it will require new overloads/wrappers to deal with @MainActor
annotated tests, and possibly will also involve the codegen in SPM.
For now I will probably disable these tests in Linux, but it would be nice to have them included. Thanks! 🙏🏼
Demo
fileprivate extension DummyTests {
static let __allTests__DummyTests = [
("testNormal", testNormal),
("testNormalThrows", testNormalThrows),
("testAsync", asyncTest(testAsync)),
("testAsyncThrows", asyncTest(testAsyncThrows)),
("testMainActor", testMainActor),
// ("testMainActorThrows", testMainActorThrows), // if we uncomment this one it infers correctly
("testMainActorAsync", asyncTest(testMainActorAsync)),
("testMainActorAsyncThrows", asyncTest(testMainActorAsyncThrows)),
]
}
fileprivate extension MainActorDummyTests {
static let __allTests__MainActorDummyTests = [
("testNormal", testNormal),
// ("testNormalThrows", testNormalThrows), // if we uncomment this one it infers correctly
("testAsync", asyncTest(testAsync)),
("testAsyncThrows", asyncTest(testAsyncThrows)),
]
}
final class DummyTests: XCTestCase {
func testNormal() {}
func testNormalThrows() throws {}
func testAsync() async {}
func testAsyncThrows() async throws {}
@MainActor func testMainActor() {}
@MainActor func testMainActorThrows() throws {}
@MainActor func testMainActorAsync() async {}
@MainActor func testMainActorAsyncThrows() async throws {}
}
@MainActor
final class MainActorDummyTests: XCTestCase {
func testNormal() {}
func testNormalThrows() throws {}
func testAsync() async {}
func testAsyncThrows() async throws {}
}
Environment
- Swift 5.7
- Ubuntu Linux 20.04 and macOS 12.6 / Xcode 14.1 (14B47b)