Skip to content

🍒[5.9][Concurrency] Handle missing Job type in old SDKs in tryDiagnoseExecutor #65413

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
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
15 changes: 8 additions & 7 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1283,19 +1283,21 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
if (funcDecl->getParameters()->size() != 1)
continue;
if (auto param = funcDecl->getParameters()->front()) {
StructDecl* jobDecl;
if (auto decl = C.getExecutorJobDecl()) {
jobDecl = decl;
} else if (auto decl = C.getJobDecl()) {
StructDecl *unownedJobDecl = C.getUnownedJobDecl();
StructDecl *jobDecl = nullptr;
if (auto executorJobDecl = C.getExecutorJobDecl()) {
jobDecl = executorJobDecl;
} else if (auto plainJobDecl = C.getJobDecl()) {
// old standard library, before we introduced the `typealias Job = ExecutorJob`
jobDecl = decl;
jobDecl = plainJobDecl;
}

if (jobDecl &&
param->getType()->isEqual(jobDecl->getDeclaredInterfaceType())) {
assert(moveOnlyEnqueueRequirement == nullptr);
moveOnlyEnqueueRequirement = funcDecl;
} else if (param->getType()->isEqual(C.getUnownedJobDecl()->getDeclaredInterfaceType())) {
} else if (unownedJobDecl &&
param->getType()->isEqual(unownedJobDecl->getDeclaredInterfaceType())) {
assert(unownedEnqueueRequirement == nullptr);
unownedEnqueueRequirement = funcDecl;
}
Expand All @@ -1306,7 +1308,6 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
break; // we're done looking for the requirements
}


auto conformance = module->lookupConformance(nominalTy, proto);
auto concreteConformance = conformance.getConcrete();
assert(unownedEnqueueRequirement && "could not find the enqueue(UnownedJob) requirement, which should be always there");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-without-job) -typecheck -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

// NOTE: This test simulates what happens when we have an SDK with some missing concurrency types.
// Specifically, we're missing the ExecutorJob and Job declarations.
// This simulates a pre-Swift-5.9 SDK being used with a Swift 5.9+ compiler,
// which would have failed previously due to missing handling of missing types.
//
// This is a regression test for that situation

final class FakeExecutor: SerialExecutor {
func enqueue(_ job: UnownedJob) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

// This simulates a pre-Swift5.9 concurrency library with `Job` and `ExecutorJob` not being defined at all.
// This is used to verify missing type handling in the SDK when a latest compiler is used.

public struct UnownedJob {}

public protocol SerialExecutor {
// pretend to be a broken, empty serial executor
func enqueue(_ job: UnownedJob)
}
14 changes: 14 additions & 0 deletions test/lit.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,20 @@ config.substitutions.append(('%build-clang-importer-objc-overlays',
'%target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -enable-objc-interop -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreFoundation.swift && '
'%target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -enable-objc-interop -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift'))


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

config.substitutions.append(('%clang-importer-sdk-concurrency-without-job-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-without-job',
'-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-without-job'))))


# 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