diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 97ee32a88a6cc..4deb4ce2fab6c 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5416,11 +5416,12 @@ NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const { if (auto *funcDecl = dyn_cast(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; } } diff --git a/stdlib/public/Concurrency/Executor.swift b/stdlib/public/Concurrency/Executor.swift index 38e0c38aadf22..115b41d9aacb8 100644 --- a/stdlib/public/Concurrency/Executor.swift +++ b/stdlib/public/Concurrency/Executor.swift @@ -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 } @@ -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 @@ -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 @@ -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)) } } diff --git a/stdlib/public/Concurrency/PartialAsyncTask.swift b/stdlib/public/Concurrency/PartialAsyncTask.swift index c0da83266789e..ffd740b8f4cb6 100644 --- a/stdlib/public/Concurrency/PartialAsyncTask.swift +++ b/stdlib/public/Concurrency/PartialAsyncTask.swift @@ -45,7 +45,7 @@ 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 @@ -53,7 +53,7 @@ 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 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 diff --git a/stdlib/public/Distributed/DistributedDefaultExecutor.swift b/stdlib/public/Distributed/DistributedDefaultExecutor.swift index 99a64fe56f4d8..37237e9a8e9db 100644 --- a/stdlib/public/Distributed/DistributedDefaultExecutor.swift +++ b/stdlib/public/Distributed/DistributedDefaultExecutor.swift @@ -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!") } diff --git a/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift b/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift index 79966f2cf19b8..de200253fecda 100644 --- a/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift +++ b/test/Concurrency/Runtime/custom_executors_complex_equality_crash.swift @@ -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()) diff --git a/test/Concurrency/Runtime/custom_executors_moveOnly_job.swift b/test/Concurrency/Runtime/custom_executors_moveOnly_job.swift index 2b4bbef7f54ba..4f4423a27e6ca 100644 --- a/test/Concurrency/Runtime/custom_executors_moveOnly_job.swift +++ b/test/Concurrency/Runtime/custom_executors_moveOnly_job.swift @@ -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()) @@ -18,6 +19,8 @@ final class InlineExecutor_UnownedJob: SerialExecutor, CustomStringConvertible { "\(Self.self)()" } } + +@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()) diff --git a/test/Concurrency/Runtime/custom_executors_priority.swift b/test/Concurrency/Runtime/custom_executors_priority.swift index f28ebfc1944be..99f7fc21d0e03 100644 --- a/test/Concurrency/Runtime/custom_executors_priority.swift +++ b/test/Concurrency/Runtime/custom_executors_priority.swift @@ -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()) } diff --git a/test/Concurrency/Runtime/custom_executors_protocol.swift b/test/Concurrency/Runtime/custom_executors_protocol.swift index aa0dd432c6229..c085fab5fc807 100644 --- a/test/Concurrency/Runtime/custom_executors_protocol.swift +++ b/test/Concurrency/Runtime/custom_executors_protocol.swift @@ -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 { diff --git a/test/Concurrency/Runtime/custom_executors_sdk_with_consuming_param_but_impl_owned.swift b/test/Concurrency/Runtime/custom_executors_sdk_with_consuming_param_but_impl_owned.swift new file mode 100644 index 0000000000000..0791ca1ad1500 --- /dev/null +++ b/test/Concurrency/Runtime/custom_executors_sdk_with_consuming_param_but_impl_owned.swift @@ -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) {} +} \ No newline at end of file diff --git a/test/Concurrency/Runtime/custom_executors_sdk_with_owned_param_but_impl_consuming.swift b/test/Concurrency/Runtime/custom_executors_sdk_with_owned_param_but_impl_consuming.swift new file mode 100644 index 0000000000000..bdda34ffe4e16 --- /dev/null +++ b/test/Concurrency/Runtime/custom_executors_sdk_with_owned_param_but_impl_consuming.swift @@ -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) {} +} \ No newline at end of file diff --git a/test/Concurrency/Runtime/custom_executors_tryDiagnoseExecutorConformance_with_sdk_missing_job_type.swift b/test/Concurrency/Runtime/custom_executors_tryDiagnoseExecutorConformance_with_sdk_missing_job_type.swift index dda2e42cf9f1e..b66a3c0b84d42 100644 --- a/test/Concurrency/Runtime/custom_executors_tryDiagnoseExecutorConformance_with_sdk_missing_job_type.swift +++ b/test/Concurrency/Runtime/custom_executors_tryDiagnoseExecutorConformance_with_sdk_missing_job_type.swift @@ -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 diff --git a/test/Concurrency/custom_executor_enqueue_impls.swift b/test/Concurrency/custom_executor_enqueue_impls.swift index 4d1943c92ec84..8d3cd562eb76e 100644 --- a/test/Concurrency/custom_executor_enqueue_impls.swift +++ b/test/Concurrency/custom_executor_enqueue_impls.swift @@ -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) @@ -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) diff --git a/test/Inputs/clang-importer-sdk/swift-modules-concurrency-consuming-job-param/_Concurrency.swift b/test/Inputs/clang-importer-sdk/swift-modules-concurrency-consuming-job-param/_Concurrency.swift new file mode 100644 index 0000000000000..427c976166a90 --- /dev/null +++ b/test/Inputs/clang-importer-sdk/swift-modules-concurrency-consuming-job-param/_Concurrency.swift @@ -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) +} \ No newline at end of file diff --git a/test/Inputs/clang-importer-sdk/swift-modules-concurrency-owned-job-param/_Concurrency.swift b/test/Inputs/clang-importer-sdk/swift-modules-concurrency-owned-job-param/_Concurrency.swift new file mode 100644 index 0000000000000..04fe535a77cf0 --- /dev/null +++ b/test/Inputs/clang-importer-sdk/swift-modules-concurrency-owned-job-param/_Concurrency.swift @@ -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) +} \ No newline at end of file diff --git a/test/lit.cfg b/test/lit.cfg index 0a24c74c02b9d..ec9c7fd9a56c4 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -634,6 +634,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'))))