Skip to content

Commit 8fbbf8d

Browse files
authored
Merge pull request swiftlang#65571 from ktoso/wip-consuming-keyword-job
[Concurrency] Adopt stable keyword consuming instead of __owned
2 parents a0ae8ee + da6f08a commit 8fbbf8d

15 files changed

+111
-17
lines changed

lib/AST/Decl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5416,11 +5416,12 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const {
54165416

54175417
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(candidate)) {
54185418
auto params = funcDecl->getParameters();
5419-
54205419
if (params->size() != 1)
54215420
continue;
54225421

5423-
if (params->get(0)->getType()->isEqual(unownedJobDecl->getDeclaredInterfaceType())) {
5422+
auto param = params->get(0);
5423+
if (param->getSpecifier() == ParamSpecifier::LegacyOwned ||
5424+
param->getSpecifier() == ParamSpecifier::Consuming) {
54245425
return funcDecl;
54255426
}
54265427
}

stdlib/public/Concurrency/Executor.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ public protocol Executor: AnyObject, Sendable {
2929
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
3030
@available(SwiftStdlib 5.9, *)
3131
@available(*, deprecated, message: "Implement 'enqueue(_: __owned ExecutorJob)' instead")
32-
func enqueue(_ job: __owned Job)
32+
func enqueue(_ job: consuming Job)
3333
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
3434

3535
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
3636
@available(SwiftStdlib 5.9, *)
37-
func enqueue(_ job: __owned ExecutorJob)
37+
func enqueue(_ job: consuming ExecutorJob)
3838
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
3939
}
4040

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

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

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

113-
public func enqueue(_ job: __owned ExecutorJob) {
113+
public func enqueue(_ job: consuming ExecutorJob) {
114114
self.enqueue(Job(job))
115115
}
116116

117-
public func enqueue(_ job: __owned Job) {
117+
public func enqueue(_ job: consuming Job) {
118118
self.enqueue(UnownedJob(job))
119119
}
120120
}

stdlib/public/Concurrency/PartialAsyncTask.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ public struct UnownedJob: Sendable {
4545
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
4646
/// Create an `UnownedJob` whose lifetime must be managed carefully until it is run exactly once.
4747
@available(SwiftStdlib 5.9, *)
48-
public init(_ job: __owned Job) {
48+
public init(_ job: __owned Job) { // must remain '__owned' in order to not break ABI
4949
self.context = job.context
5050
}
5151
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
5252

5353
#if !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY
5454
/// Create an `UnownedJob` whose lifetime must be managed carefully until it is run exactly once.
5555
@available(SwiftStdlib 5.9, *)
56-
public init(_ job: __owned ExecutorJob) {
56+
public init(_ job: __owned ExecutorJob) { // must remain '__owned' in order to not break ABI
5757
self.context = job.context
5858
}
5959
#endif // !SWIFT_STDLIB_TASK_TO_THREAD_MODEL_CONCURRENCY

stdlib/public/Distributed/DistributedDefaultExecutor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ internal final class DistributedRemoteActorReferenceExecutor: SerialExecutor {
2424
internal init() {}
2525

2626
@inlinable
27-
public func enqueue(_ job: __owned ExecutorJob) {
27+
public func enqueue(_ job: consuming ExecutorJob) {
2828
let jobDescription = job.description
2929
fatalError("Attempted to enqueue ExecutorJob (\(jobDescription)) on executor of remote distributed actor reference!")
3030
}

test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class NaiveQueueExecutor: SerialExecutor, CustomStringConvertible {
2323
self.queue = queue
2424
}
2525

26-
public func enqueue(_ job: __owned ExecutorJob) {
26+
public func enqueue(_ job: consuming ExecutorJob) {
2727
let unowned = UnownedJob(job)
2828
queue.sync {
2929
unowned.runSynchronously(on: self.asUnownedSerialExecutor())

test/Concurrency/Runtime/custom_executors_moveOnly_job.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// UNSUPPORTED: back_deployment_runtime
1010
// REQUIRES: concurrency_runtime
1111

12+
@available(*, deprecated, message: "Test type to verify deprecated API still works")
1213
final class InlineExecutor_UnownedJob: SerialExecutor, CustomStringConvertible {
1314
public func enqueue(_ job: UnownedJob) {
1415
job.runSynchronously(on: self.asUnownedSerialExecutor())
@@ -18,6 +19,8 @@ final class InlineExecutor_UnownedJob: SerialExecutor, CustomStringConvertible {
1819
"\(Self.self)()"
1920
}
2021
}
22+
23+
@available(*, deprecated, message: "Test type to verify deprecated API still works")
2124
final class InlineExecutor_Job: SerialExecutor, CustomStringConvertible {
2225
public func enqueue(_ job: __owned Job) {
2326
job.runSynchronously(on: self.asUnownedSerialExecutor())

test/Concurrency/Runtime/custom_executors_priority.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// REQUIRES: concurrency_runtime
1111

1212
final class InlineExecutor: SerialExecutor {
13-
public func enqueue(_ job: __owned ExecutorJob) {
13+
public func enqueue(_ job: consuming ExecutorJob) {
1414
print("\(self): enqueue (priority: \(TaskPriority(job.priority)!))")
1515
job.runSynchronously(on: self.asUnownedSerialExecutor())
1616
}

test/Concurrency/Runtime/custom_executors_protocol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ final class NaiveQueueExecutor: SpecifiedExecutor, CustomStringConvertible {
3535
self.queue = queue
3636
}
3737

38-
public func enqueue(_ job: __owned ExecutorJob) {
38+
public func enqueue(_ job: consuming ExecutorJob) {
3939
print("\(self): enqueue")
4040
let unowned = UnownedJob(job)
4141
queue.sync {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-consuming-job-param) -emit-sil -parse-as-library %s -verify
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: libdispatch
5+
6+
// rdar://106849189 move-only types should be supported in freestanding mode
7+
// UNSUPPORTED: freestanding
8+
9+
// UNSUPPORTED: back_deployment_runtime
10+
// REQUIRES: concurrency_runtime
11+
12+
import _Concurrency
13+
14+
final class FakeExecutor: SerialExecutor {
15+
// implements the __owned requirement in "old" SDK:
16+
// func enqueue(_ job: __owned Job)
17+
func enqueue(_ job: __owned ExecutorJob) {}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-owned-job-param) -emit-sil -parse-as-library %s -verify
2+
3+
// REQUIRES: concurrency
4+
// REQUIRES: libdispatch
5+
6+
// rdar://106849189 move-only types should be supported in freestanding mode
7+
// UNSUPPORTED: freestanding
8+
9+
// UNSUPPORTED: back_deployment_runtime
10+
// REQUIRES: concurrency_runtime
11+
12+
import _Concurrency
13+
14+
final class FakeExecutor: SerialExecutor {
15+
// implements the __owned requirement in "old" SDK:
16+
// func enqueue(_ job: __owned Job)
17+
func enqueue(_ job: consuming ExecutorJob) {}
18+
}

test/Concurrency/Runtime/custom_executors_tryDiagnoseExecutorConformance_with_sdk_missing_job_type.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-without-job) -typecheck -parse-as-library %s -verify
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-without-job) -emit-sil -parse-as-library %s -verify
22

33
// REQUIRES: concurrency
44
// REQUIRES: libdispatch

test/Concurrency/custom_executor_enqueue_impls.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ final class TripleExecutor: SerialExecutor {
4141
// expected-note@+1{{use 'ExecutorJob' instead}}
4242
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}}
4343

44-
func enqueue(_ job: __owned ExecutorJob) {}
44+
func enqueue(_ job: consuming ExecutorJob) {}
4545

4646
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
4747
UnownedSerialExecutor(ordinary: self)
@@ -72,7 +72,19 @@ final class StillDeprecated: SerialExecutor {
7272

7373
/// Just implementing the new signature causes no warnings, good.
7474
final class NewExecutor: SerialExecutor {
75-
func enqueue(_ job: __owned ExecutorJob) {} // no warnings
75+
func enqueue(_ job: consuming ExecutorJob) {} // no warnings
76+
77+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
78+
UnownedSerialExecutor(ordinary: self)
79+
}
80+
}
81+
82+
// Good impl, but missing the ownership keyword
83+
final class MissingOwnership: SerialExecutor {
84+
func enqueue(_ job: ExecutorJob) {} // expected-error{{noncopyable parameter must specify its ownership}}
85+
// expected-note@-1{{add 'borrowing' for an immutable reference}}
86+
// expected-note@-2{{add 'inout' for a mutable reference}}
87+
// expected-note@-3{{add 'consuming' to take the value from the caller}}
7688

7789
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
7890
UnownedSerialExecutor(ordinary: self)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
// This simulates a pre-Swift5.9 concurrency library with an consuming declaration rather than __owned.
3+
// This allows us to confirm the compiler and sdk can be mismatched but we'll build correctly.
4+
5+
@_moveOnly
6+
public struct ExecutorJob {}
7+
8+
public protocol SerialExecutor {
9+
// pretend old SDK with `__owned` param rather than ``
10+
func enqueue(_ job: consuming ExecutorJob)
11+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
// This simulates a pre-Swift5.9 concurrency library with an __owned declaration rather than consuming.
3+
// This allows us to confirm the compiler and sdk can be mismatched but we'll build correctly.
4+
5+
@_moveOnly
6+
public struct ExecutorJob {}
7+
8+
public protocol SerialExecutor {
9+
// pretend old SDK with `__owned` param rather than ``
10+
func enqueue(_ job: __owned ExecutorJob)
11+
}

test/lit.cfg

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,26 @@ config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-j
634634
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
635635
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-typealias-struct-job'))))
636636

637+
# FIXME: BEGIN -enable-source-import hackaround
638+
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param-path',
639+
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
640+
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param-nosource',
641+
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
642+
# FIXME: END -enable-source-import hackaround
643+
config.substitutions.append(('%clang-importer-sdk-concurrency-consuming-job-param',
644+
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
645+
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-consuming-job-param'))))
646+
647+
# FIXME: BEGIN -enable-source-import hackaround
648+
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param-path',
649+
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
650+
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param-nosource',
651+
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
652+
# FIXME: END -enable-source-import hackaround
653+
config.substitutions.append(('%clang-importer-sdk-concurrency-owned-job-param',
654+
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
655+
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-owned-job-param'))))
656+
637657
# FIXME: BEGIN -enable-source-import hackaround
638658
config.substitutions.append(('%clang-importer-sdk-path',
639659
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))

0 commit comments

Comments
 (0)