davbeck
(David Beck)
1
I can't seem to figure out how to get default arguments to work with global actors. Marking either the class or the init method as MainActor doesn't seem to do anything.
@MainActor
class FakeFileDownloader: FileDownloader {
@MainActor
// Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
init(sessionManager: SessionManager = SessionManager()) {
3 Likes
I have the same problem, including in Xcode 13.3 beta 3 (13E5104i).
Reported as https://bugs.swift.org/browse/SR-15916
An ugly workaround is to define an unsafe nonisolated initializer:
@MainActor class Foo {
init() { } // The safe one
nonisolated init(unsafeNonisolated: Bool) { } // Here be dragons
}
// error: call to main actor-isolated initializer 'init()' in a synchronous nonisolated context
// @MainActor func f1(foo: Foo = Foo()) { }
// ^
// note: calls to initializer 'init()' from outside of its actor context are implicitly asynchronous
// @MainActor class Foo {
// ^
@MainActor func f1(foo: Foo = Foo()) { }
// OK
@MainActor func f1(foo: Foo = Foo(unsafeNonisolated: true)) { }
1 Like
millenomi
(Aura Lily Vulcano)
3
One note here that the general diagnostic does seem incorrect, but a reminder that that code is inlined in the caller's context. An off-actor call to:
let it = await FakeFileDownloader()
is equivalent to:
let value = SessionManager()
let it = await FakeFileDownloader(sessionManager: value)
which is clearly not correct for an arbitrary context. It may not be just a matter of allowing the syntax you propose.
Which syntax are you talking about?
One single default argument can "easily" replaced with two overloads. But several arguments can not:
@MainActor class Foo {}
// ❌ Won't compile
@MainActor func f(foo: Foo = Foo()) { ... }
// ✅ OK: replace with 2 overloads
@MainActor func f(foo: Foo) { ... }
@MainActor func f() { f(foo: Foo()) }
// ❌ Won't compile, can be replaced with 4 overloads
@MainActor func f(foo: Foo = Foo(), bar: Bar = Bar()) { ... }
// ❌ Won't compile, can be replaced with 8 overloads
@MainActor func f(foo: Foo = Foo(), bar: Bar = Bar(), baz: Baz = Baz()) { ... }
millenomi
(Aura Lily Vulcano)
5
Yeah, sorry, to be more clear: I meant here that the execution environment in which the default value is computed is not trivial, and thus whoever fixes that bug — which is definitely worth fixing — may have to make choices about tightening the semantics of default arguments in order to fix this.
1 Like
shiz
6
Hi, is there any update about this topic?
Swift 5.9 Label has been added in the above Github issue. So, is there going to be any change on Swift 5.9?
To clarify, these version labels indicate the latest (dev or release) version known to contain the issue, not the version the issue is planned to be fixed in.
2 Likes
shiz
8
Thank you for the reply. I misunderstood the meaning of the label, sorry.