Skip to content

Commit 8fbf0e0

Browse files
committed
[Concurrency] Fix asSerialExecutor() for complex equality.
Complex equality is encoded in the low bit of the witness table pointer. We need to mask off the low bits when bitcasting to an `any SerialExecutor`. rdar://164005854
1 parent dad2637 commit 8fbf0e0

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

stdlib/public/Concurrency/Executor.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,13 @@ public struct UnownedSerialExecutor: Sendable {
808808

809809
@available(StdlibDeploymentTarget 6.2, *)
810810
public func asSerialExecutor() -> (any SerialExecutor)? {
811-
return unsafe unsafeBitCast(executor, to: (any SerialExecutor)?.self)
811+
// The low bits of the witness table are used to encode the executor kind.
812+
// any SerialExecutor needs a raw witness table pointer, so mask off the low
813+
// bits, knowing the witness table pointer is aligned to the pointer size.
814+
let rawExecutorData = unsafe unsafeBitCast(executor, to: (UInt, UInt).self)
815+
let mask = ~(UInt(MemoryLayout<UnsafeRawPointer>.alignment) - 1)
816+
let alignedExecutor = unsafe (rawExecutorData.0, rawExecutorData.1 & mask)
817+
return unsafe unsafeBitCast(alignedExecutor, to: (any SerialExecutor)?.self)
812818
}
813819
}
814820

test/Concurrency/Runtime/custom_executors_complex_equality.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ actor MyActor {
6666

6767
func test(expectedExecutor: NaiveQueueExecutor, expectedQueue: DispatchQueue) {
6868
expectedExecutor.preconditionIsolated("Expected deep equality to trigger for \(expectedExecutor) and our \(self.executor)")
69+
70+
// Ensure we get a usable value from asSerialExecutor() when the executor
71+
// has complex equality.
72+
_ = expectedExecutor.asUnownedSerialExecutor().asSerialExecutor()!.asUnownedSerialExecutor()
73+
6974
print("\(Self.self): [\(self.executor.name)] on same context as [\(expectedExecutor.name)]")
7075
}
7176
}

0 commit comments

Comments
 (0)