From 9a3c3f94cb793cc841269bff021ca7b26c27d2ec Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Fri, 7 Apr 2023 19:04:50 +0900 Subject: [PATCH 1/2] [Concurerncy] SE feedback: rename Job to ExecutorJob, stage using a typealias for now --- stdlib/public/Concurrency/Executor.swift | 30 +++++++++---------- .../public/Concurrency/PartialAsyncTask.swift | 17 +++++++---- .../custom_executor_enqueue_impls.swift | 4 +-- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/stdlib/public/Concurrency/Executor.swift b/stdlib/public/Concurrency/Executor.swift index 49c1390dddc4e..6b2185355d17b 100644 --- a/stdlib/public/Concurrency/Executor.swift +++ b/stdlib/public/Concurrency/Executor.swift @@ -17,16 +17,16 @@ import Swift public protocol Executor: AnyObject, Sendable { #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY - @available(macOS, introduced: 10.15, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(iOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(watchOS, introduced: 6.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(tvOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") + @available(macOS, introduced: 10.15, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(iOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(watchOS, introduced: 6.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(tvOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY func enqueue(_ job: UnownedJob) #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY @available(SwiftStdlib 5.9, *) - func enqueue(_ job: __owned Job) + func enqueue(_ job: __owned ExecutorJob) #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY } @@ -39,10 +39,10 @@ public protocol SerialExecutor: Executor { // work-scheduling operation. @_nonoverride #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY - @available(macOS, introduced: 10.15, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(iOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(watchOS, introduced: 6.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") - @available(tvOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned Job)' instead") + @available(macOS, introduced: 10.15, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(iOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(watchOS, introduced: 6.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") + @available(tvOS, introduced: 13.0, deprecated: 9999, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead") #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY func enqueue(_ job: UnownedJob) @@ -53,7 +53,7 @@ public protocol SerialExecutor: Executor { // work-scheduling operation. @_nonoverride @available(SwiftStdlib 5.9, *) - func enqueue(_ job: __owned Job) + func enqueue(_ job: __owned ExecutorJob) #endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY /// Convert this executor value to the optimized form of borrowed @@ -87,10 +87,10 @@ public protocol SerialExecutor: Executor { @available(SwiftStdlib 5.9, *) extension Executor { public func enqueue(_ job: UnownedJob) { - self.enqueue(Job(job)) + self.enqueue(ExecutorJob(job)) } - public func enqueue(_ job: __owned Job) { + public func enqueue(_ job: __owned ExecutorJob) { self.enqueue(UnownedJob(job)) } } @@ -219,10 +219,10 @@ func _checkExpectedExecutor(_filenameStart: Builtin.RawPointer, /// Primarily a debug utility. /// -/// If the passed in Job is a Task, returns the complete 64bit TaskId, +/// If the passed in ExecutorJob is a Task, returns the complete 64bit TaskId, /// otherwise returns only the job's 32bit Id. /// -/// - Returns: the Id stored in this Job or Task, for purposes of debug printing +/// - Returns: the Id stored in this ExecutorJob or Task, for purposes of debug printing @available(SwiftStdlib 5.9, *) @_silgen_name("swift_task_getJobTaskId") internal func _getJobTaskId(_ job: UnownedJob) -> UInt64 @@ -250,7 +250,7 @@ internal func _enqueueOnExecutor(job unownedJob: UnownedJob, executor: E) where E: SerialExecutor { #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY if #available(SwiftStdlib 5.9, *) { - executor.enqueue(Job(context: unownedJob._context)) + executor.enqueue(ExecutorJob(context: unownedJob._context)) } else { executor.enqueue(unownedJob) } diff --git a/stdlib/public/Concurrency/PartialAsyncTask.swift b/stdlib/public/Concurrency/PartialAsyncTask.swift index cd0482124521b..5f375b965af61 100644 --- a/stdlib/public/Concurrency/PartialAsyncTask.swift +++ b/stdlib/public/Concurrency/PartialAsyncTask.swift @@ -13,7 +13,7 @@ import Swift @_implementationOnly import _SwiftConcurrencyShims -// TODO(swift): rename the file to Job.swift eventually, we don't use PartialTask terminology anymore +// TODO(swift): rename the file to ExecutorJob.swift eventually, we don't use PartialTask terminology anymore @available(SwiftStdlib 5.1, *) @_silgen_name("swift_job_run") @@ -65,7 +65,7 @@ public struct UnownedJob: Sendable { /// Deprecated API to run a job on a specific executor. @_alwaysEmitIntoClient @inlinable - @available(*, deprecated, renamed: "Job.runSynchronously(on:)") + @available(*, deprecated, renamed: "ExecutorJob.runSynchronously(on:)") public func _runSynchronously(on executor: UnownedSerialExecutor) { _swiftJobRun(self, executor) } @@ -105,6 +105,11 @@ extension UnownedJob: CustomStringConvertible { } #if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY + +@available(macOS 9999, iOS 9999, watchOS 9999, tvOS 9999, *) +@available(*, deprecated, renamed: "ExecutorJob") +public typealias Job = ExecutorJob + /// A unit of scheduleable work. /// /// Unless you're implementing a scheduler, @@ -112,7 +117,7 @@ extension UnownedJob: CustomStringConvertible { @available(SwiftStdlib 5.9, *) @frozen @_moveOnly -public struct Job: Sendable { +public struct ExecutorJob: Sendable { internal var context: Builtin.Job @usableFromInline @@ -145,7 +150,7 @@ public struct Job: Sendable { } @available(SwiftStdlib 5.9, *) -extension Job { +extension ExecutorJob { /// Run this job on the passed in executor. /// @@ -158,7 +163,7 @@ extension Job { /// /// This operation consumes the job, preventing it accidental use after it has ben run. /// - /// Converting a `Job` to an ``UnownedJob`` and invoking ``UnownedJob/runSynchronously(_:)` on it multiple times is undefined behavior, + /// Converting a `ExecutorJob` to an ``UnownedJob`` and invoking ``UnownedJob/runSynchronously(_:)` on it multiple times is undefined behavior, /// as a job can only ever be run once, and must not be accessed after it has been run. /// /// - Parameter executor: the executor this job will be semantically running on. @@ -182,7 +187,7 @@ extension Job { /// However, the semantics of how priority is treated are left up to each /// platform and `Executor` implementation. /// -/// A Job's priority is roughly equivalent to a `TaskPriority`, +/// A ExecutorJob's priority is roughly equivalent to a `TaskPriority`, /// however, since not all jobs are tasks, represented as separate type. /// /// Conversions between the two priorities are available as initializers on the respective types. diff --git a/test/Concurrency/custom_executor_enqueue_impls.swift b/test/Concurrency/custom_executor_enqueue_impls.swift index b24d3dc159086..46db955cced2f 100644 --- a/test/Concurrency/custom_executor_enqueue_impls.swift +++ b/test/Concurrency/custom_executor_enqueue_impls.swift @@ -25,7 +25,7 @@ final class OldExecutor: SerialExecutor { /// That's why we do log the deprecation warning, people should use the move-only version. final class BothExecutor: SerialExecutor { func enqueue(_ job: UnownedJob) {} // expected-warning{{'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; conform type 'BothExecutor' to 'Executor' by implementing 'func enqueue(Job)' instead}} - func enqueue(_ job: __owned Job) {} + func enqueue(_ job: __owned ExecutorJob) {} func asUnownedSerialExecutor() -> UnownedSerialExecutor { UnownedSerialExecutor(ordinary: self) @@ -45,7 +45,7 @@ final class NoneExecutor: SerialExecutor { // expected-error{{type 'NoneExecutor /// Just implementing the new signature causes no warnings, good. final class NewExecutor: SerialExecutor { - func enqueue(_ job: __owned Job) {} // no warnings + func enqueue(_ job: __owned ExecutorJob) {} // no warnings func asUnownedSerialExecutor() -> UnownedSerialExecutor { UnownedSerialExecutor(ordinary: self) From 5f21846289131c801bc47c32ab032a4e70803692 Mon Sep 17 00:00:00 2001 From: Konrad `ktoso` Malawski Date: Mon, 10 Apr 2023 18:11:02 +0900 Subject: [PATCH 2/2] [Concurrency] Handle ExecutorJob/Job better during renaming period --- include/swift/AST/KnownSDKTypes.def | 3 ++- lib/Sema/TypeCheckConcurrency.cpp | 14 +++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/swift/AST/KnownSDKTypes.def b/include/swift/AST/KnownSDKTypes.def index f9d0c2a0c24c1..a281f059b3931 100644 --- a/include/swift/AST/KnownSDKTypes.def +++ b/include/swift/AST/KnownSDKTypes.def @@ -39,7 +39,8 @@ KNOWN_SDK_TYPE_DECL(ObjectiveC, ObjCBool, StructDecl, 0) // standardized KNOWN_SDK_TYPE_DECL(Concurrency, UnsafeContinuation, NominalTypeDecl, 2) KNOWN_SDK_TYPE_DECL(Concurrency, MainActor, NominalTypeDecl, 0) -KNOWN_SDK_TYPE_DECL(Concurrency, Job, StructDecl, 0) +KNOWN_SDK_TYPE_DECL(Concurrency, Job, StructDecl, 0) // TODO: remove in favor of ExecutorJob +KNOWN_SDK_TYPE_DECL(Concurrency, ExecutorJob, StructDecl, 0) KNOWN_SDK_TYPE_DECL(Concurrency, UnownedJob, StructDecl, 0) KNOWN_SDK_TYPE_DECL(Concurrency, Executor, NominalTypeDecl, 0) KNOWN_SDK_TYPE_DECL(Concurrency, SerialExecutor, NominalTypeDecl, 0) diff --git a/lib/Sema/TypeCheckConcurrency.cpp b/lib/Sema/TypeCheckConcurrency.cpp index 532e32f6e5e50..d6cd8ea4af40f 100644 --- a/lib/Sema/TypeCheckConcurrency.cpp +++ b/lib/Sema/TypeCheckConcurrency.cpp @@ -1276,7 +1276,7 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C, auto module = nominal->getParentModule(); Type nominalTy = nominal->getDeclaredInterfaceType(); - // enqueue(_: UnownedJob) + // enqueue(_:) auto enqueueDeclName = DeclName(C, DeclBaseName(C.Id_enqueue), { Identifier() }); FuncDecl *unownedEnqueueRequirement = nullptr; @@ -1293,8 +1293,16 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C, if (funcDecl->getParameters()->size() != 1) continue; if (auto param = funcDecl->getParameters()->front()) { - if (C.getJobDecl() && - param->getType()->isEqual(C.getJobDecl()->getDeclaredInterfaceType())) { + StructDecl* jobDecl; + if (auto decl = C.getExecutorJobDecl()) { + jobDecl = decl; + } else if (auto decl = C.getJobDecl()) { + // old standard library, before we introduced the `typealias Job = ExecutorJob` + jobDecl = decl; + } + + if (jobDecl && + param->getType()->isEqual(jobDecl->getDeclaredInterfaceType())) { assert(moveOnlyEnqueueRequirement == nullptr); moveOnlyEnqueueRequirement = funcDecl; } else if (param->getType()->isEqual(C.getUnownedJobDecl()->getDeclaredInterfaceType())) {