swiftxcodeswift-concurrencyswift6swift-testing

Why does a Swift test think my simple struct is main actor-isolated?


My experience with Swift 6 strict concurrency so far doesn't match my understanding of implicit MainActor isolation semantics.

TL;DR

Build succeeds when testing a struct declared in the test module, but fails when the struct is moved to the main module:

Main actor-isolated property … cannot be accessed from outside the actor.

Steps to reproduce
  1. Open up Xcode 26 beta 2 on macOS 26 (probably also ok on current stables).
  2. Create a new Swift app with Swift testing, no storage. Call it WhatTheSwift.
  3. Set the Swift Language Version on all three targets to Swift 6.

Update the default test file to be this:

import Testing
@testable import WhatTheSwift

struct WhatTheSwiftTests {
    @Test func example() async throws {
        let thing = Thing(foo: "bar")
        #expect(thing.foo == "bar")
    }
}

struct Thing {
    let foo: String
}

That should build fine, and the tests should pass.

Now, move the Thing declaration into its own Thing.swift file in the WhatTheSwift module, and try running the test again. You should see this:

Error as presented in Xcode 26

Observations
My question

Why? And why only when Thing is in a different module?


Solution

  • It looks like the explanation has two parts.

    The difference between the struct being declared in the test module and the main module is the SWIFT_DEFAULT_ACTOR_ISOLATION setting. It is set to MainActor in the main module, but isn't available in the test module, presumably because the test framework would break if it was set that way.

    The assumption that Thing shouldn't be affected by this setting was false, due in no small part to ChatGPT being supremely convincing in its hallucinatory responses while I've been chewing over this peculiarity the last couple of days. Default actor isolation affects everything.