Skip to content

Commit b847ee1

Browse files
committed
Further hardening: new compiler + old SDK still diagnose correctly
1 parent 8d6980e commit b847ee1

File tree

6 files changed

+99
-12
lines changed

6 files changed

+99
-12
lines changed

include/swift/AST/Decl.h

+2
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

+41-2
Original file line numberDiff line numberDiff line change
@@ -5343,7 +5343,8 @@ NominalTypeDecl::getExecutorOwnedEnqueueFunction() const {
53435343
if (params->size() != 1)
53445344
continue;
53455345

5346-
if (params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned && // TODO: make this Consuming
5346+
if ((params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned ||
5347+
params->get(0)->getSpecifier() == ParamSpecifier::Consuming) &&
53475348
params->get(0)->getInterfaceType()->isEqual(executorJobDecl->getDeclaredInterfaceType())) {
53485349
return funcDecl;
53495350
}
@@ -5381,7 +5382,8 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const {
53815382
if (params->size() != 1)
53825383
continue;
53835384

5384-
if (params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned && // TODO: make this Consuming
5385+
if ((params->get(0)->getSpecifier() == ParamSpecifier::LegacyOwned ||
5386+
params->get(0)->getSpecifier() == ParamSpecifier::Consuming) &&
53855387
params->get(0)->getType()->isEqual(legacyJobDecl->getDeclaredInterfaceType())) {
53865388
return funcDecl;
53875389
}
@@ -5391,6 +5393,43 @@ NominalTypeDecl::getExecutorLegacyOwnedEnqueueFunction() const {
53915393
return nullptr;
53925394
}
53935395

5396+
AbstractFunctionDecl *
5397+
NominalTypeDecl::getExecutorLegacyUnownedEnqueueFunction() const {
5398+
auto &C = getASTContext();
5399+
StructDecl *unownedJobDecl = C.getUnownedJobDecl();
5400+
if (!unownedJobDecl)
5401+
return nullptr;
5402+
5403+
auto proto = dyn_cast<ProtocolDecl>(this);
5404+
if (!proto)
5405+
return nullptr;
5406+
5407+
llvm::SmallVector<ValueDecl *, 2> results;
5408+
lookupQualified(getSelfNominalTypeDecl(),
5409+
DeclNameRef(C.Id_enqueue),
5410+
NL_ProtocolMembers,
5411+
results);
5412+
5413+
for (auto candidate: results) {
5414+
// we're specifically looking for the Executor protocol requirement
5415+
if (!isa<ProtocolDecl>(candidate->getDeclContext()))
5416+
continue;
5417+
5418+
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(candidate)) {
5419+
auto params = funcDecl->getParameters();
5420+
5421+
if (params->size() != 1)
5422+
continue;
5423+
5424+
if (params->get(0)->getType()->isEqual(unownedJobDecl->getDeclaredInterfaceType())) {
5425+
return funcDecl;
5426+
}
5427+
}
5428+
}
5429+
5430+
return nullptr;
5431+
}
5432+
53945433
ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
53955434
ArrayRef<InheritedEntry> Inherited,
53965435
GenericParamList *GenericParams, DeclContext *Parent,

lib/Sema/TypeCheckConcurrency.cpp

+18-8
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+
}
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

+9-2
Original file line numberDiff line numberDiff line change
@@ -616,15 +616,22 @@ config.substitutions.append(('%build-clang-importer-objc-overlays',
616616
# FIXME: BEGIN -enable-source-import hackaround
617617
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job-path',
618618
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
619-
620619
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job-nosource',
621620
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
622621
# FIXME: END -enable-source-import hackaround
623-
624622
config.substitutions.append(('%clang-importer-sdk-concurrency-without-job',
625623
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
626624
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-without-job'))))
627625

626+
# FIXME: BEGIN -enable-source-import hackaround
627+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job-path',
628+
'%r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
629+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job-nosource',
630+
'-sdk %r' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'))))
631+
# FIXME: END -enable-source-import hackaround
632+
config.substitutions.append(('%clang-importer-sdk-concurrency-typealias-struct-job',
633+
'-enable-source-import -sdk %r -I %r ' % (make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk'),
634+
make_path(config.test_source_root, 'Inputs', 'clang-importer-sdk', 'swift-modules-concurrency-typealias-struct-job'))))
628635

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

0 commit comments

Comments
 (0)