Skip to content

🍒[5.9][Concurrency] Adopt stable keyword consuming instead of __owned #65575

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 1 commit into from
May 19, 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
5 changes: 3 additions & 2 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5404,11 +5404,12 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const {

if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(candidate)) {
auto params = funcDecl->getParameters();

if (params->size() != 1)
continue;

if (params->get(0)->getType()->isEqual(unownedJobDecl->getDeclaredInterfaceType())) {
auto param = params->get(0);
if (param->getSpecifier() == ParamSpecifier::LegacyOwned ||
param->getSpecifier() == ParamSpecifier::Consuming) {
return funcDecl;
}
}
Expand Down
12 changes: 6 additions & 6 deletions stdlib/public/Concurrency/Executor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ public protocol Executor: AnyObject, Sendable {
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@available(SwiftStdlib 5.9, *)
@available(*, deprecated, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead")
func enqueue(_ job: __owned Job)
func enqueue(_ job: consuming Job)
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
@available(SwiftStdlib 5.9, *)
func enqueue(_ job: __owned ExecutorJob)
func enqueue(_ job: consuming ExecutorJob)
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
}

Expand All @@ -60,7 +60,7 @@ public protocol SerialExecutor: Executor {
@_nonoverride
@available(SwiftStdlib 5.9, *)
@available(*, deprecated, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead")
func enqueue(_ job: __owned Job)
func enqueue(_ job: consuming Job)
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
Expand All @@ -70,7 +70,7 @@ public protocol SerialExecutor: Executor {
// work-scheduling operation.
@_nonoverride
@available(SwiftStdlib 5.9, *)
func enqueue(_ job: __owned ExecutorJob)
func enqueue(_ job: consuming ExecutorJob)
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

/// Convert this executor value to the optimized form of borrowed
Expand Down Expand Up @@ -110,11 +110,11 @@ extension Executor {
self.enqueue(ExecutorJob(job))
}

public func enqueue(_ job: __owned ExecutorJob) {
public func enqueue(_ job: consuming ExecutorJob) {
self.enqueue(Job(job))
}

public func enqueue(_ job: __owned Job) {
public func enqueue(_ job: consuming Job) {
self.enqueue(UnownedJob(job))
}
}
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/Concurrency/PartialAsyncTask.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ public struct UnownedJob: Sendable {
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
/// Create an `UnownedJob` whose lifetime must be managed carefully until it is run exactly once.
@available(SwiftStdlib 5.9, *)
public init(_ job: __owned Job) {
public init(_ job: __owned Job) { // must remain '__owned' in order to not break ABI
self.context = job.context
}
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
/// Create an `UnownedJob` whose lifetime must be managed carefully until it is run exactly once.
@available(SwiftStdlib 5.9, *)
public init(_ job: __owned ExecutorJob) {
public init(_ job: __owned ExecutorJob) { // must remain '__owned' in order to not break ABI
self.context = job.context
}
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/Distributed/DistributedDefaultExecutor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
internal init() {}

@inlinable
public func enqueue(_ job: __owned ExecutorJob) {
public func enqueue(_ job: consuming ExecutorJob) {
let jobDescription = job.description
fatalError("Attempted to enqueue ExecutorJob (\(jobDescription)) on executor of remote distributed actor reference!")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ final class NaiveQueueExecutor: SerialExecutor, CustomStringConvertible {
self.queue = queue
}

public func enqueue(_ job: __owned ExecutorJob) {
public func enqueue(_ job: consuming ExecutorJob) {
let unowned = UnownedJob(job)
queue.sync {
unowned.runSynchronously(on: self.asUnownedSerialExecutor())
Expand Down
2 changes: 2 additions & 0 deletions test/Concurrency/Runtime/custom_executors_moveOnly_job.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// UNSUPPORTED: back_deployment_runtime
// REQUIRES: concurrency_runtime

@available(*, deprecated, message: "Test type to verify deprecated API still works")
final class InlineExecutor_UnownedJob: SerialExecutor, CustomStringConvertible {
public func enqueue(_ job: UnownedJob) {
job.runSynchronously(on: self.asUnownedSerialExecutor())
Expand All @@ -19,6 +20,7 @@ final class InlineExecutor_UnownedJob: SerialExecutor, CustomStringConvertible {
}
}

@available(*, deprecated, message: "Test type to verify deprecated API still works")
final class InlineExecutor_Job: SerialExecutor, CustomStringConvertible {
public func enqueue(_ job: __owned Job) {
job.runSynchronously(on: self.asUnownedSerialExecutor())
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/custom_executors_priority.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// REQUIRES: concurrency_runtime

final class InlineExecutor: SerialExecutor {
public func enqueue(_ job: __owned ExecutorJob) {
public func enqueue(_ job: consuming ExecutorJob) {
print("\(self): enqueue (priority: \(TaskPriority(job.priority)!))")
job.runSynchronously(on: self.asUnownedSerialExecutor())
}
Expand Down
2 changes: 1 addition & 1 deletion test/Concurrency/Runtime/custom_executors_protocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class NaiveQueueExecutor: SpecifiedExecutor, CustomStringConvertible {
self.queue = queue
}

public func enqueue(_ job: __owned ExecutorJob) {
public func enqueue(_ job: consuming ExecutorJob) {
print("\(self): enqueue")
let unowned = UnownedJob(job)
queue.sync {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-consuming-job-param) -emit-sil -parse-as-library %s -verify

// REQUIRES: concurrency
// REQUIRES: libdispatch

// rdar://106849189 move-only types should be supported in freestanding mode
// UNSUPPORTED: freestanding

// UNSUPPORTED: back_deployment_runtime
// REQUIRES: concurrency_runtime

import _Concurrency

final class FakeExecutor: SerialExecutor {
// implements the __owned requirement in "old" SDK:
// func enqueue(_ job: __owned Job)
func enqueue(_ job: __owned ExecutorJob) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-owned-job-param) -emit-sil -parse-as-library %s -verify

// REQUIRES: concurrency
// REQUIRES: libdispatch

// rdar://106849189 move-only types should be supported in freestanding mode
// UNSUPPORTED: freestanding

// UNSUPPORTED: back_deployment_runtime
// REQUIRES: concurrency_runtime

import _Concurrency

final class FakeExecutor: SerialExecutor {
// implements the __owned requirement in "old" SDK:
// func enqueue(_ job: __owned Job)
func enqueue(_ job: consuming ExecutorJob) {}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-without-job) -typecheck -parse-as-library %s -verify
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-without-job) -emit-sil -parse-as-library %s -verify

// REQUIRES: concurrency
// REQUIRES: libdispatch
Expand Down
16 changes: 14 additions & 2 deletions test/Concurrency/custom_executor_enqueue_impls.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ final class TripleExecutor: SerialExecutor {
// expected-note@+1{{use 'ExecutorJob' instead}}
func enqueue(_ job: __owned Job) {} // expected-warning{{'Executor.enqueue(Job)' is deprecated as a protocol requirement; conform type 'TripleExecutor' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}

func enqueue(_ job: __owned ExecutorJob) {}
func enqueue(_ job: consuming ExecutorJob) {}

func asUnownedSerialExecutor() -> UnownedSerialExecutor {
UnownedSerialExecutor(ordinary: self)
Expand Down Expand Up @@ -72,7 +72,19 @@ final class StillDeprecated: SerialExecutor {

/// Just implementing the new signature causes no warnings, good.
final class NewExecutor: SerialExecutor {
func enqueue(_ job: __owned ExecutorJob) {} // no warnings
func enqueue(_ job: consuming ExecutorJob) {} // no warnings

func asUnownedSerialExecutor() -> UnownedSerialExecutor {
UnownedSerialExecutor(ordinary: self)
}
}

// Good impl, but missing the ownership keyword
final class MissingOwnership: SerialExecutor {
func enqueue(_ job: ExecutorJob) {} // expected-error{{noncopyable parameter must specify its ownership}}
// expected-note@-1{{add 'borrowing' for an immutable reference}}
// expected-note@-2{{add 'inout' for a mutable reference}}
// expected-note@-3{{add 'consuming' to take the value from the caller}}

func asUnownedSerialExecutor() -> UnownedSerialExecutor {
UnownedSerialExecutor(ordinary: self)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

// This simulates a pre-Swift5.9 concurrency library with an consuming declaration rather than __owned.
// This allows us to confirm the compiler and sdk can be mismatched but we'll build correctly.

@_moveOnly
public struct ExecutorJob {}

public protocol SerialExecutor {
// pretend old SDK with `__owned` param rather than ``
func enqueue(_ job: consuming ExecutorJob)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

// This simulates a pre-Swift5.9 concurrency library with an __owned declaration rather than consuming.
// This allows us to confirm the compiler and sdk can be mismatched but we'll build correctly.

@_moveOnly
public struct ExecutorJob {}

public protocol SerialExecutor {
// pretend old SDK with `__owned` param rather than ``
func enqueue(_ job: __owned ExecutorJob)
}
20 changes: 20 additions & 0 deletions test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,26 @@ config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-j
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-typealias-struct-job'))))

# FIXME: BEGIN -enable-source-import hackaround
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param-path',
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param-nosource',
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
# FIXME: END -enable-source-import hackaround
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param',
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-consuming-job-param'))))

# FIXME: BEGIN -enable-source-import hackaround
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param-path',
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param-nosource',
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
# FIXME: END -enable-source-import hackaround
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param',
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-owned-job-param'))))

# FIXME: BEGIN -enable-source-import hackaround
config.substitutions.append(('%clang-importer-sdk-path',
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
Expand Down