Skip to content

Keypath literals are created in disconnected regions allowing them to be sent to another isolation and cause data race #80388

Open
@nickolas-pohilets

Description

@nickolas-pohilets

Description

Keypaths to global actor-isolated properties can be sent to other isolation domains and used there.

Reproduction

@MainActor
class MA {
  var x: Int = 0
}

actor MyActor {
  func hack(ma: MA, keyPath: sending ReferenceWritableKeyPath<MA, Int>) {
    ma[keyPath: keyPath] += 1
  }
}

@MainActor func test() async -> Int {
  let a = MyActor()
  let ma = MA()
  Task {
    await Task.yield()
    await a.hack(ma: ma, keyPath: \MA.x) // ⚠️ passes!
  }
  await Task.yield()
  return ma.x
}

var counts: [Int] = Array(repeating: 0, count: 2)
for _ in 0..<1000 {
  counts[await test()] += 1
}
print(counts) // e.g. [997, 3]

Expected behavior

Keypath literals to global-actor isolated properties should be created in regions connected to that actor, to prevent them from being sent to other isolation domains.

Environment

Nightly toolchain - compiles, runs and produces output

Apple Swift version 6.2-dev (LLVM 21406e90d7382d7, Swift 90340a069a706c3)
Target: arm64-apple-macosx15.0
Build config: +assertions

Xcode-16.1 - compiles, runs but traps

swift-driver version: 1.115 Apple Swift version 6.0.2 (swiftlang-6.0.2.1.2 clang-1600.0.26.4)
Target: arm64-apple-macosx15.0

Additional information

No response

Metadata

Metadata

Assignees

Labels

bugA 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