Skip to content

[Concurrency] Rename Job to ExecutorJob, ease transition with typealias #65006

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/swift/AST/KnownSDKTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 11 additions & 3 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1266,7 +1266,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;
Expand All @@ -1283,8 +1283,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())) {
Expand Down
30 changes: 15 additions & 15 deletions stdlib/public/Concurrency/Executor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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)

Expand All @@ -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
Expand Down Expand Up @@ -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))
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -250,7 +250,7 @@ internal func _enqueueOnExecutor<E>(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)
}
Expand Down
17 changes: 11 additions & 6 deletions stdlib/public/Concurrency/PartialAsyncTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -105,14 +105,19 @@ 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,
/// you don't generally interact with jobs directly.
@available(SwiftStdlib 5.9, *)
@frozen
@_moveOnly
public struct Job: Sendable {
public struct ExecutorJob: Sendable {
internal var context: Builtin.Job

@usableFromInline
Expand Down Expand Up @@ -145,7 +150,7 @@ public struct Job: Sendable {
}

@available(SwiftStdlib 5.9, *)
extension Job {
extension ExecutorJob {

/// Run this job on the passed in executor.
///
Expand All @@ -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.
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/Distributed/DistributedDefaultExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
@inlinable
public func enqueue(_ job: __owned Job) {
let jobDescription = job.description
fatalError("Attempted to enqueue \(Job.self) (\(jobDescription)) on executor of remote distributed actor reference!")
fatalError("Attempted to enqueue \(ExecutorJob.self) (\(jobDescription)) on executor of remote distributed actor reference!")
}

public func asUnownedSerialExecutor() -> UnownedSerialExecutor {
Expand All @@ -50,4 +50,4 @@ public func buildDefaultDistributedRemoteActorExecutor<Act>(
_ actor: Act
) -> UnownedSerialExecutor where Act: DistributedActor {
return DistributedRemoteActorReferenceExecutor.sharedUnownedExecutor
}
}
4 changes: 2 additions & 2 deletions test/Concurrency/custom_executor_enqueue_impls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ actor EnqueueTest {
}

tests.test("remote actor reference should have crash-on-enqueue executor") {
expectCrashLater(withMessage: "Attempted to enqueue Job (Job(id: 1)) on executor of remote distributed actor reference!")
expectCrashLater(withMessage: "Attempted to enqueue ExecutorJob (ExecutorJob(id: 1)) on executor of remote distributed actor reference!")
// we do the bad idea of taking an executor from a remote worker
// and then force another actor to run on it; this will cause an enqueue on the "crash on enqueue" executor.
let wrongUse = EnqueueTest(unownedExecutor: normalRemoteWorker.unownedExecutor)
Expand Down