func getActions() -> [String: Action] {
return [
"abc": { @MainActor in print("abc") }, // ⚠️ Converting function value of type '@MainActor () -> ()' to '() -> Void' loses global actor 'MainActor'; this is an error in the Swift 6 language mode
"xyz": { @MainActor in print("xyz") } // ⚠️ Converting function value of type '@MainActor () -> ()' to '() -> Void' loses global actor 'MainActor'; this is an error in the Swift 6 language mode
]
}
It seems that adding -warn-concurrency to the Swift 5 target fixes the issue, aligning dictionary types as Dictionary<String, @MainActor @Sendable () -> ()>.
@Douglas_Gregor, @beccadax, is it expected that @preconcurrency works only in tandem with -warn-concurrency?
EDIT: But with -warn-concurrency calls to Action in MyApp also trigger the error, while calls to useIt() do not. Is this another bug?
Since MyLib is compiled with -swift-version 6, why bother putting @preconcurrency on those 2 nominal decls? There shouldn't be any crash after removing those 2 occurrences of @preconcurrency in MyLib.
Because MyApp is compiled in Swift 5 and is still missing concurrency annotations. Without @preconcurrency usages of those APIs in MyApp trigger an error even with -strict-concurrency=minimal.
The consequence of using @preconcurrency on MyLib.Action is, at all use sites with minimal concurrency checking, Action will be treated as () -> Void instead of the preferred @MainActor @Sendable () -> Void)(reference).
I agree a relevant runtime conversion crash is surprising (although not common), but is understandable from my perspective.
Playing with this further, with generic types that don't have special treat (i.e. other than Array, Set, Dictionary), compiler produces a compilation error:
// MyLib: Swift 6
public struct Box<T> {
public var value: T
public init(value: T) {
self.value = value
}
}
@preconcurrency @MainActor
public func useBox(_ box: Box<Action>) {
box.value()
}
// MyApp: Swift 5, minimal checking
func getBox() -> Box<Action> {
return Box { print("box") }
}
useBox(getBox()) // error: Cannot convert value of type 'Box<() -> Void>' to expected argument type 'Box<Action>' (aka 'Box<@MainActor @Sendable () -> ()>')
Should compiler produce the same error for the Array, Set and Dictionary? @Douglas_Gregor, @beccadax, WDYT?