I am having trouble understanding why the "await" keyword is needed when accessing a variable within a Task with weak self capturing.
You can see that in the actor below, Task 1 compiles successfully, whereas Task 2 encounters a compile error:
actor MyActor {
private var name = ""
func printName() {
// Task 1
Task {
print(name)
}
// Task 2
Task { [weak self] in
// Error: Expression is 'async' but is not marked with 'await'
// Why "await" is needed here?
print(self?.name ?? "")
}
}
}
The way I understand it is that spinning a new Task takes you outside of the current actor, which is why accessing the actor requires await as you would access it from another actor (like the @MainActor)
No, Tasks inherit actor context, and that fact is likely at the root of this issue. Since weak self creates a new reference to self, the compiler likely sees it as a different actor than self, thus requiring await to access it since the Task's is running on self there. Whether weak references should have that behavior I don't know, but that seems to be the likely explanation.
That doesn't make sense to me. The whole point of reference types is that the references are completely interchangeable, as they point to the same object.
You mean that's the point of weak references? I'm not sure I'd describe them as interchangeable, but it makes sense to me that without specific support, the compiler's analysis of actor safety may not consider them equivalent. Perhaps the optional is fouling the analysis? I don't know, this is only speculation, we need a real expert to weigh in.