Skip to content

Compiler fails to enforce hopping in closure within lazy variable initializer of a custom actor #81937

Closed as not planned
@rayx

Description

@rayx

Description

See the code below. task is a lazy variable in a custom actor. Its initialization code has a closure with @MainActor isolation. await should be required to call the custom actor's method self.update(1). But compiler fails to enforce it.

Reproduction

actor MyActor {
    var value: Int = 0
    lazy var task = Task { @MainActor in
        self.update(1)
    } 
    
    func update(_ value :Int) {
        self.value = value
    }

    func test() async {
        print("before running task: \(self.value)")
        await print("task result: \(task.result)")
        print("after running task: \(self.value)")
    }
}

func test() async {
    let a = MyActor()
    await a.test()
}

await test()

The code compiles and runs successfully, but it shouldn't.

Expected behavior

It shouldn't compile.

Environment

$ swift --version
Swift version 6.0.3 (swift-6.0.3-RELEASE)
Target: x86_64-unknown-linux-gnu

Additional information

I did more experiments, which might help to narrow down the root cause.

  1. The following code has the same issue. So the issue isn't caused by capturing self in the closure.
    lazy var task = Task { @MainActor in
-        self.update(1)
+        MyActor().update(1)
    } 
  1. Global variable doesn't have this issue.
    var task = Task { @MainActor in
        await MyActor().update(1)
    } 

Metadata

Metadata

Assignees

No one assigned

    Labels

    actor isolationFeature → concurrency: Actor isolationbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.compilerThe Swift compiler itselfconcurrencyFeature: umbrella label for concurrency language featuresswift 6.0

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions