swift icon indicating copy to clipboard operation
swift copied to clipboard

Overridden methods can't have different actor isolation from nonisolated overridden declaration

Open NachoSoto opened this issue 1 year ago • 6 comments

Description

This is the same as https://github.com/swiftlang/swift/issues/75732, but a different example from init. This makes working with XCTest almost impossible with Xcode 16.

Reproduction

@MainActor
final class MainActorType {
  init() {}
}

@MainActor
final class TestsForMainActorType: XCTestCase {
  // Main actor-isolated instance method 'setUp()' has different actor isolation from nonisolated overridden declaration
  @MainActor
  override func setUp() {
    super.setUp()

    // Removing `@MainActor` means this can't be called:
    // Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
    type = .init()

    // Can't call anything on `type` as preparation for every test, and same for `tearDown`.
  }

  private var type: MainActorType?
}

Expected behavior

This compiles

Environment

swift-driver version: 1.113 Apple Swift version 6.0 (swiftlang-6.0.0.7.6 clang-1600.0.24.1)
Target: arm64-apple-macosx14.0

NachoSoto avatar Aug 09 '24 23:08 NachoSoto

cc @hborla

NachoSoto avatar Aug 09 '24 23:08 NachoSoto

This is just one particular example with XCTest, but the bigger issue is that there are still lots of Apple frameworks that aren't ready for Swift 6, like Combine.

NachoSoto avatar Aug 09 '24 23:08 NachoSoto

or GameplayKit

clns avatar Aug 13 '24 09:08 clns

Basically anything that calls UIKit from any of the setUp/tearDown methods. This is a major impediment.

jonreid avatar Sep 18 '24 00:09 jonreid

Having the same issue on Stevia unit tests. One trick is to make setUp async throws like so:

@MainActor class LayoutTests: XCTestCase {
    
    var v: UIView!
    
    override func setUp() async throws {
//        try await super.setUp() -> errors: Sending main actor-isolated value of type 'XCTestCase' with later accesses to nonisolated context risks causing data races
        v = UIView()
    }

But then calling super.setUp() errors out. @NachoSoto any news?

s4cha avatar Sep 22 '24 03:09 s4cha

Nope. The reality is that XCTest (like Combine and many other Apple frameworks) isn't ready for Swift Concurrency.

NachoSoto avatar Sep 22 '24 03:09 NachoSoto

Hey, I must have lived under a rock but I just realized new Swift Testing was I out so in my case it's just a matter of migrating XCTests to new Swift Testing \o/

s4cha avatar Sep 24 '24 05:09 s4cha

But then calling super.setUp() errors out.

@s4cha If you mark the test class itself as Sendable then it works:

@MainActor final class LayoutTests: XCTestCase, Sendable {
  ...
}

bbrk24 avatar Oct 03 '24 15:10 bbrk24

@hborla I think this is solved by SE-0470?

NachoSoto avatar May 10 '25 16:05 NachoSoto

Oh never mind, that's only for protocol conformances.

NachoSoto avatar May 10 '25 16:05 NachoSoto

Yes that's right, SE-0470 is only for protocol conformances. I'm working on a proposal to apply similar techniques to subclasses to allow isolated overrides like this (using the basic approach outlined in the vision document). I think there are also similar challenges with metatypes.

hborla avatar Jun 20 '25 05:06 hborla