Why "await" is needed to access a variable within an actor when using a weak self Task?

Hi,

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 ?? "")
        }
    }
}

Thanks in advance for clarifying.

3 Likes

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.

3 Likes

That does make a lot of sense. Thanks for the clear 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.

1 Like

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.

The optional is fouling analysis AFAIR, we’ve seen this and it’s worth creating an issue on GitHub for it

2 Likes

Oh, sorry, this just proves how confusing this thing is still for me.

Thanks for the kind response. I have opened an issue: “await” is needed to access a variable within an actor when using a Task with optional self · Issue #66748 · apple/swift · GitHub

3 Likes