Skip to content

Commit b4ca869

Browse files
committed
Further hardening: new compiler + old SDK still diagnose correctly
1 parent 365b44a commit b4ca869

File tree

6 files changed

+99
-12
lines changed

6 files changed

+99
-12
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3884,6 +3884,8 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
38843884
/// This method should be deprecated and removed
38853885
/// Get the move-only `enqueue(Job)` protocol requirement function on the `Executor` protocol.
38863886
AbstractFunctionDecl *getExecutorLegacyOwnedEnqueueFunction() const;
3887+
/// Get the move-only `enqueue(UnownedJob)` protocol requirement function on the `Executor` protocol.
3888+
AbstractFunctionDecl *getExecutorLegacyUnownedEnqueueFunction() const;
38873889

38883890
/// Collect the set of protocols to which this type should implicitly
38893891
/// conform, such as AnyObject (for classes).

lib/AST/Decl.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5330,7 +5330,8 @@ NominalTypeDecl::getExecutorOwnedEnqueueFunction() const {
53305330
if (params->size() != 1)
53315331
continue;
53325332

5333-
if (params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned && // TODO: make this Consuming
5333+
if ((params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned ||
5334+
params->get(0)->getSpecifier() == ParamSpecifier::Consuming) &&
53345335
params->get(0)->getInterfaceType()->isEqual(executorJobDecl->getDeclaredInterfaceType())) {
53355336
return funcDecl;
53365337
}
@@ -5368,7 +5369,8 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const {
53685369
if (params->size() != 1)
53695370
continue;
53705371

5371-
if (params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned && // TODO: make this Consuming
5372+
if ((params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned ||
5373+
params->get(0)->getSpecifier() == ParamSpecifier::Consuming) &&
53725374
params->get(0)->getType()->isEqual(legacyJobDecl->getDeclaredInterfaceType())) {
53735375
return funcDecl;
53745376
}
@@ -5378,6 +5380,43 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const {
53785380
return nullptr;
53795381
}
53805382

5383+
AbstractFunctionDecl *
5384+
NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const {
5385+
auto &C = getASTContext();
5386+
StructDecl *unownedJobDecl = C.getUnownedJobDecl();
5387+
if (!unownedJobDecl)
5388+
return nullptr;
5389+
5390+
auto proto = dyn_cast<ProtocolDecl>(this);
5391+
if (!proto)
5392+
return nullptr;
5393+
5394+
llvm::SmallVector<ValueDecl *, 2> results;
5395+
lookupQualified(getSelfNominalTypeDecl(),
5396+
DeclNameRef(C.Id_enqueue),
5397+
NL_ProtocolMembers,
5398+
results);
5399+
5400+
for (auto candidate: results) {
5401+
// we're specifically looking for the Executor protocol requirement
5402+
if (!isa<ProtocolDecl>(candidate->getDeclContext()))
5403+
continue;
5404+
5405+
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(candidate)) {
5406+
auto params = funcDecl->getParameters();
5407+
5408+
if (params->size() != 1)
5409+
continue;
5410+
5411+
if (params->get(0)->getType()->isEqual(unownedJobDecl->getDeclaredInterfaceType())) {
5412+
return funcDecl;
5413+
}
5414+
}
5415+
}
5416+
5417+
return nullptr;
5418+
}
5419+
53815420
ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
53825421
ArrayRef<InheritedEntry> Inherited,
53835422
GenericParamList *GenericParams, DeclContext *Parent,

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,14 +1343,24 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13431343
(!legacyMoveOnlyEnqueueWitnessDecl || legacyMoveOnlyEnqueueWitnessDecl->getLoc().isInvalid())) {
13441344
// Neither old nor new implementation have been found, but we provide default impls for them
13451345
// that are mutually recursive, so we must error and suggest implementing the right requirement.
1346-
auto ownedRequirement = C.getExecutorDecl()->getExecutorOwnedEnqueueFunction();
1347-
nominal->diagnose(diag::type_does_not_conform, nominalTy, proto->getDeclaredInterfaceType());
1348-
ownedRequirement->diagnose(diag::no_witnesses,
1349-
getProtocolRequirementKind(ownedRequirement),
1350-
ownedRequirement->getName(),
1351-
ownedRequirement->getParameters()->get(0)->getInterfaceType(),
1352-
/*AddFixIt=*/true);
1353-
return;
1346+
//
1347+
// If we're running against an SDK that does not have the ExecutorJob enqueue function,
1348+
// try to diagnose using the next-best one available.
1349+
auto missingRequirement = C.getExecutorDecl()->getExecutorOwnedEnqueueFunction();
1350+
if (!missingRequirement)
1351+
missingRequirement = C.getExecutorDecl()->getExecutorLegacyOwnedEnqueueFunction();
1352+
if (!missingRequirement)
1353+
missingRequirement = C.getExecutorDecl()->getExecutorLegacyUnownedEnqueueFunction();
1354+
1355+
if (missingRequirement) {
1356+
nominal->diagnose(diag::type_does_not_conform, nominalTy, proto->getDeclaredInterfaceType());
1357+
missingRequirement->diagnose(diag::no_witnesses,
1358+
getProtocolRequirementKind(missingRequirement),
1359+
missingRequirement->getName(),
1360+
missingRequirement->getParameters()->get(0)->getInterfaceType(),
1361+
/*AddFixIt=*/true);
1362+
return;
1363+
}
13541364
}
13551365
}
13561366

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-concurrency-typealias-struct-job) -typecheck -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 FakeExecutor1: SerialExecutor {
15+
func enqueue(_ job: __owned ExecutorJob) {}
16+
}
17+
18+
final class FakeExecutor2: SerialExecutor {
19+
func enqueue(_ job: __owned Job) {}
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
@_moveOnly
3+
public struct ExecutorJob {}
4+
5+
public typealias Job = ExecutorJob
6+
7+
public protocol SerialExecutor {
8+
func enqueue(_ job: __owned ExecutorJob)
9+
}

test/lit.cfg

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,15 +611,22 @@ config.substitutions.append(('%build-clang-importer-objc-overlays',
611611
# FIXME: BEGIN -enable-source-import hackaround
612612
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job-path',
613613
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
614-
615614
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job-nosource',
616615
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
617616
# FIXME: END -enable-source-import hackaround
618-
619617
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job',
620618
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
621619
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-without-job'))))
622620

621+
# FIXME: BEGIN -enable-source-import hackaround
622+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job-path',
623+
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
624+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job-nosource',
625+
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
626+
# FIXME: END -enable-source-import hackaround
627+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job',
628+
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
629+
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-typealias-struct-job'))))
623630

624631
# FIXME: BEGIN -enable-source-import hackaround
625632
config.substitutions.append(('%clang-importer-sdk-path',

0 commit comments

Comments
 (0)