Here's another one I'm less sure of, but I'm not clear on why this wouldn't work:
@MainActor final class C {}
@MainActor protocol P: AnyObject {}
struct S {
// Happy days
static let defaultValueA: C? = nil
// Static property 'defaultValueB' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
static let defaultValueB: P? = nil
}
These checks are not very reliable yet. For example:
import Foundation
@MainActor func mainThreadCall() {}
func foo() {
DispatchQueue.main.async(execute: mainThreadCall) // β (expected)
let queue = DispatchQueue.main
queue.async(execute: mainThreadCall)
// πΆβ°β warning: converting function value of type '@MainActor () -> ()' to '@convention(block) () -> Void' loses global actor 'MainActor'; this is an error in the Swift 6 language mode
}
func baz() {
struct DispatchQueue {
static let main = Foundation.DispatchQueue.global()
}
DispatchQueue.main.async(execute: mainThreadCall) // β but should be a warning
}
Thanks, all. Good to hear there's some fixes on the way. It's quite tough, as a lot of the time the diagnostics are very useful, but other times I'm questioning whether I'm misunderstanding something or the compiler is throwing a false positive.
Does anyone have any thoughts on the below? Should this be legal?
I am not sure about that, but it seems it should be safe to declare a global variable in that way. It is isolated on the global actor, so it is sendable by definition. But can be wrong on that one.
Here's a simplified version of one of my current classes. Before Xcode 15.3, I was not getting these warnings.
@MainActor
class UIHandler {
private let transformer: Transformer
private let viewFactory: ViewFactory
nonisolated init(
transformer: Transformer,
viewFactory: ViewFactory
) {
self.transformer = transformer // Main actor-isolated property 'transformer' can not be mutated from a non-isolated context; this is an error in Swift 6
self.viewFactory = viewStateFactory // Main actor-isolated property 'viewFactory' can not be mutated from a non-isolated context; this is an error in Swift 6
}
}
protocol Transformer {}
final class ViewFactory {}
This warning is confusing because it states these properties are actor isolated, but they are not, from my understanding, given they are immutable.
I did find that marking the dependencies as Sendable keeps the compiler happy. Is marking @MainActor dependencies as Sendable a good approach, or is this a compiler bug?
Warning is confusing, yet the case here is that they are crossing isolation boundary - from the nonisolated init to the main actor isolation. And only sendable types can safely cross isolation boundary, so Sendable fixes that.
The rest depends on the use case. If your class is going to be initialized on main actor, you can make init isolated as well, therefore there will be no crossing of isolation boundary. Otherwise, conforming to Sendable is a go right now.
But yes, there's baked-in knowledge about main dispatch queue like this.
// That will be funβ’ if/when we decide to allow changing the main actor's executor to an custom executor someday, but that'll be an adventure for another time