Skip to content

Sendable checking hole when actors call non-mutating async methods on non-Sendable types #65315

@FranzBusch

Description

@FranzBusch

Description
The following code compiles without errors under strict concurrency checking but has a maybe not so obvious but extremely dangerous data race.

struct Counter {
    private var counter = 0
    mutating func increment() async {
        self.counter += 1
    }
}

final class Wrapper {
    private var counter = Counter()

    func increment() async {
        await self.counter.increment()
    }
}

actor Bar {
  private var counter = Wrapper()

  func bar() async {
    await self.counter.increment()
  }
}

This is a tricky situation because the intention of the above code is often to make a non-Sendable type thread safe by storing it inside an actor. However, the compiler fails to diagnose that we are sending an instance of Wrapper across an isolation domain by calling the async function. The compiler must check here that calling any async non-mutating method on a non-Sendable type isn't safe.

Expected behavior
The above code should generate a warning under strict Concurrency checking since it is exhibiting a data race.

rdar://108309344

Metadata

Metadata

Assignees

No one assigned

    Labels

    actorFeature → concurrency: `actor` declarationsbugA deviation from expected or documented behavior. Also: expected but undesirable behavior.concurrencyFeature: umbrella label for concurrency language features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions