Skip to content

Commit 8469d80

Browse files
committed
Fix compile errors for Swift 6 language mode
1 parent 6ae9a05 commit 8469d80

File tree

6 files changed

+70
-41
lines changed

6 files changed

+70
-41
lines changed

Sources/AsyncAlgorithms_XCTest/ValidationTest.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension XCTestCase {
2424
#endif
2525
}
2626

27-
func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
27+
func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
2828
var expectations = expectedFailures
2929
var result: AsyncSequenceValidationDiagram.ExpectationResult?
3030
var failures = [AsyncSequenceValidationDiagram.ExpectationFailure]()
@@ -62,15 +62,15 @@ extension XCTestCase {
6262
}
6363
}
6464

65-
func validate<Test: AsyncSequenceValidationTest>(expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
65+
func validate<Test: AsyncSequenceValidationTest>(expectedFailures: Set<String>, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
6666
validate(theme: .ascii, expectedFailures: expectedFailures, build, file: file, line: line)
6767
}
6868

69-
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
69+
public func validate<Test: AsyncSequenceValidationTest, Theme: AsyncSequenceValidationTheme>(theme: Theme, @AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
7070
validate(theme: theme, expectedFailures: [], build, file: file, line: line)
7171
}
7272

73-
public func validate<Test: AsyncSequenceValidationTest>(@AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #file, line: UInt = #line) {
73+
public func validate<Test: AsyncSequenceValidationTest>(@AsyncSequenceValidationDiagram _ build: (AsyncSequenceValidationDiagram) -> Test, file: StaticString = #filePath, line: UInt = #line) {
7474
validate(theme: .ascii, expectedFailures: [], build, file: file, line: line)
7575
}
7676
}

Sources/AsyncSequenceValidation/Clock.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ extension AsyncSequenceValidationDiagram.Clock {
115115
let token = queue.prepare()
116116
try await withTaskCancellationHandler {
117117
try await withUnsafeThrowingContinuation { continuation in
118-
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob, deadline: deadline, continuation: continuation, token: token)
118+
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob.value, deadline: deadline, continuation: continuation, token: token)
119119
}
120120
} onCancel: {
121121
queue.cancel(token)

Sources/AsyncSequenceValidation/Input.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ extension AsyncSequenceValidationDiagram {
5252
}
5353
return try await withTaskCancellationHandler {
5454
try await withUnsafeThrowingContinuation { continuation in
55-
queue.enqueue(Context.currentJob, deadline: when, continuation: continuation, results[eventIndex], index: index, token: token)
55+
queue.enqueue(Context.currentJob.value, deadline: when, continuation: continuation, results[eventIndex], index: index, token: token)
5656
}
5757
} onCancel: { [queue] in
5858
queue.cancel(token)

Sources/AsyncSequenceValidation/TaskDriver.swift

+6-6
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ import Glibc
2020
#endif
2121

2222
#if canImport(Darwin)
23-
func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
23+
@Sendable func start_thread(_ raw: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
2424
Unmanaged<TaskDriver>.fromOpaque(raw).takeRetainedValue().run()
2525
return nil
2626
}
2727
#elseif canImport(Glibc)
28-
func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
28+
@Sendable func start_thread(_ raw: UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer? {
2929
Unmanaged<TaskDriver>.fromOpaque(raw!).takeRetainedValue().run()
3030
return nil
3131
}
@@ -77,11 +77,11 @@ final class TaskDriver {
7777

7878
func enqueue(_ job: JobRef) {
7979
let job = Job(job)
80-
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob) {
81-
let previous = AsyncSequenceValidationDiagram.Context.currentJob
82-
AsyncSequenceValidationDiagram.Context.currentJob = job
80+
queue.enqueue(AsyncSequenceValidationDiagram.Context.currentJob.value) {
81+
let previous = AsyncSequenceValidationDiagram.Context.currentJob.value
82+
AsyncSequenceValidationDiagram.Context.currentJob.setValue(job)
8383
job.execute()
84-
AsyncSequenceValidationDiagram.Context.currentJob = previous
84+
AsyncSequenceValidationDiagram.Context.currentJob.setValue(previous)
8585
}
8686
}
8787
}

Sources/AsyncSequenceValidation/Test.swift

+57-28
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//
1010
//===----------------------------------------------------------------------===//
1111

12-
import _CAsyncSequenceValidationSupport
12+
@preconcurrency import _CAsyncSequenceValidationSupport
1313
import AsyncAlgorithms
1414

1515
@_silgen_name("swift_job_run")
@@ -48,17 +48,17 @@ extension AsyncSequenceValidationDiagram {
4848
do {
4949
if let pastEnd = try await iterator.next(){
5050
let failure = ExpectationFailure(
51-
when: Context.clock!.now,
51+
when: Context.clock.value!.now,
5252
kind: .specificationViolationGotValueAfterIteration(pastEnd),
5353
specification: output)
54-
Context.specificationFailures.append(failure)
54+
Context.specificationFailures.withValue { $0.append(failure) }
5555
}
5656
} catch {
5757
let failure = ExpectationFailure(
58-
when: Context.clock!.now,
58+
when: Context.clock.value!.now,
5959
kind: .specificationViolationGotFailureAfterIteration(error),
6060
specification: output)
61-
Context.specificationFailures.append(failure)
61+
Context.specificationFailures.withValue { $0.append(failure) }
6262
}
6363
} catch {
6464
throw error
@@ -107,7 +107,7 @@ extension AsyncSequenceValidationDiagram {
107107
}
108108
}
109109

110-
private static let _executor: AnyObject = {
110+
private static let _executor: any SerialExecutor = {
111111
if #available(macOS 14.0, iOS 17.0, watchOS 10.0, tvOS 17.0, *) {
112112
return ClockExecutor_5_9()
113113
} else {
@@ -116,19 +116,19 @@ extension AsyncSequenceValidationDiagram {
116116
}()
117117

118118
static var unownedExecutor: UnownedSerialExecutor {
119-
(_executor as! any SerialExecutor).asUnownedSerialExecutor()
119+
_executor.asUnownedSerialExecutor()
120120
}
121121
#endif
122122

123-
static var clock: Clock?
124-
125-
126-
127-
static var driver: TaskDriver?
123+
static let clock = LockIsolated<Clock?>(nil)
124+
128125

129-
static var currentJob: Job?
130126

131-
static var specificationFailures = [ExpectationFailure]()
127+
static let driver = LockIsolated<TaskDriver?>(nil)
128+
129+
static let currentJob = LockIsolated<Job?>(nil)
130+
131+
static let specificationFailures = LockIsolated<[ExpectationFailure]>([])
132132
}
133133

134134
enum ActualResult {
@@ -158,9 +158,9 @@ extension AsyncSequenceValidationDiagram {
158158
actual: [(Clock.Instant, Result<String?, Error>)]
159159
) -> (ExpectationResult, [ExpectationFailure]) {
160160
let result = ExpectationResult(expected: expected, actual: actual)
161-
var failures = Context.specificationFailures
162-
Context.specificationFailures.removeAll()
163-
161+
var failures = Context.specificationFailures.value
162+
Context.specificationFailures.withValue { $0.removeAll() }
163+
164164
let actualTimes = actual.map { when, _ in when }
165165
let expectedTimes = expected.map { $0.when }
166166

@@ -349,14 +349,14 @@ extension AsyncSequenceValidationDiagram {
349349
}
350350

351351
let actual = ManagedCriticalState([(Clock.Instant, Result<String?, Error>)]())
352-
Context.clock = clock
353-
Context.specificationFailures.removeAll()
352+
Context.clock.setValue(clock)
353+
Context.specificationFailures.withValue { $0.removeAll() }
354354
// This all needs to be isolated from potential Tasks (the caller function might be async!)
355-
Context.driver = TaskDriver(queue: diagram.queue) { driver in
355+
Context.driver.setValue(TaskDriver(queue: diagram.queue) { driver in
356356
swift_task_enqueueGlobal_hook = { job, original in
357-
Context.driver?.enqueue(job)
357+
Context.driver.value?.enqueue(job)
358358
}
359-
359+
360360
let runner = Task {
361361
do {
362362
try await test.test(with: clock, activeTicks: activeTicks, output: test.output) { event in
@@ -389,15 +389,15 @@ extension AsyncSequenceValidationDiagram {
389389
}
390390

391391
runner.cancel()
392-
Context.clock = nil
392+
Context.clock.setValue(nil)
393393
swift_task_enqueueGlobal_hook = nil
394-
}
395-
Context.driver?.start()
394+
})
395+
Context.driver.value?.start()
396396
// This is only valid since we are doing tests here
397397
// else wise this would cause QoS inversions
398-
Context.driver?.join()
399-
Context.driver = nil
400-
398+
Context.driver.value?.join()
399+
Context.driver.setValue(nil)
400+
401401
return validate(
402402
inputs: test.inputs,
403403
output: test.output,
@@ -412,3 +412,32 @@ extension AsyncSequenceValidationDiagram {
412412
try self.test(theme: .ascii, build)
413413
}
414414
}
415+
416+
final class LockIsolated<Value>: @unchecked Sendable {
417+
private var _value: Value
418+
private let lock = Lock.allocate()
419+
420+
init(_ value: @autoclosure @Sendable () throws -> Value) rethrows {
421+
self._value = try value()
422+
}
423+
424+
func setValue(_ newValue: @autoclosure @Sendable () throws -> Value) rethrows {
425+
try self.lock.withLock {
426+
self._value = try newValue()
427+
}
428+
}
429+
430+
var value: Value {
431+
self.lock.withLock {
432+
self._value
433+
}
434+
}
435+
436+
func withValue<T: Sendable>(_ operation: @Sendable (inout Value) throws -> T) rethrows -> T {
437+
try self.lock.withLock {
438+
var value = self._value
439+
defer { self._value = value }
440+
return try operation(&value)
441+
}
442+
}
443+
}

Tests/AsyncAlgorithmsTests/Support/Asserts.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ public func XCTAssertEqual<A: Equatable, B: Equatable, C: Equatable>(_ expressio
154154
@available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *)
155155
internal func XCTAssertThrowsError<T>(
156156
_ expression: @autoclosure () async throws -> T,
157-
file: StaticString = #file,
157+
file: StaticString = #filePath,
158158
line: UInt = #line,
159159
verify: (Error) -> Void = { _ in }
160160
) async {

0 commit comments

Comments
 (0)