Skip to content

Commit d0b6f4e

Browse files
committed
dont use loc validity to determine if we should diagnose; instead, error if all implementations are "default from stdlib" because end-user MUST implement at least one of them
1 parent 5621ab3 commit d0b6f4e

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
12761276
auto &diags = C.Diags;
12771277
auto module = nominal->getParentModule();
12781278
Type nominalTy = nominal->getDeclaredInterfaceType();
1279+
NominalTypeDecl *executorDecl = C.getExecutorDecl();
12791280

12801281
// enqueue(_:)
12811282
auto enqueueDeclName = DeclName(C, DeclBaseName(C.Id_enqueue), { Identifier() });
@@ -1324,18 +1325,18 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13241325
assert(unownedEnqueueRequirement && "could not find the enqueue(UnownedJob) requirement, which should be always there");
13251326

13261327
// try to find at least a single implementations of enqueue(_:)
1327-
ConcreteDeclRef unownedEnqueueWitness = concreteConformance->getWitnessDeclRef(unownedEnqueueRequirement);
1328-
ValueDecl *unownedEnqueueWitnessDecl = unownedEnqueueWitness.getDecl();
1328+
// auto unownedEnqueueWitness = concreteConformance->getWitnessDeclRef(unownedEnqueueRequirement);
1329+
ValueDecl *unownedEnqueueWitnessDecl = concreteConformance->getWitnessDecl(unownedEnqueueRequirement); // unownedEnqueueWitness.getDecl();
13291330
ValueDecl *moveOnlyEnqueueWitnessDecl = nullptr;
13301331
ValueDecl *legacyMoveOnlyEnqueueWitnessDecl = nullptr;
13311332

13321333
if (moveOnlyEnqueueRequirement) {
1333-
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1334-
moveOnlyEnqueueRequirement).getDecl();
1334+
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1335+
moveOnlyEnqueueRequirement);
13351336
}
13361337
if (legacyMoveOnlyEnqueueRequirement) {
1337-
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1338-
legacyMoveOnlyEnqueueRequirement).getDecl();
1338+
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1339+
legacyMoveOnlyEnqueueRequirement);
13391340
}
13401341

13411342
// --- Diagnose warnings and errors
@@ -1360,24 +1361,42 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13601361

13611362
// If both old and new enqueue are implemented, but the old one cannot be removed,
13621363
// emit a warning that the new enqueue is unused.
1363-
if (!canRemoveOldDecls &&
1364-
unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid() &&
1365-
moveOnlyEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1364+
if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
13661365
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unused_implementation);
13671366
}
13681367

13691368
// Old UnownedJob based impl is present, warn about it suggesting the new protocol requirement.
1370-
if (canRemoveOldDecls && unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid()) {
1369+
if (canRemoveOldDecls && unownedEnqueueWitnessDecl) {
13711370
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unowned_implementation, nominalTy);
13721371
}
13731372
// Old Job based impl is present, warn about it suggesting the new protocol requirement.
1374-
if (legacyMoveOnlyEnqueueWitnessDecl && legacyMoveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1373+
if (legacyMoveOnlyEnqueueWitnessDecl) {
13751374
diags.diagnose(legacyMoveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_deprecated_owned_job_implementation, nominalTy);
13761375
}
13771376

1378-
if ((!unownedEnqueueWitnessDecl || unownedEnqueueWitnessDecl->getLoc().isInvalid()) &&
1379-
(!moveOnlyEnqueueWitnessDecl || moveOnlyEnqueueWitnessDecl->getLoc().isInvalid()) &&
1380-
(!legacyMoveOnlyEnqueueWitnessDecl || legacyMoveOnlyEnqueueWitnessDecl->getLoc().isInvalid())) {
1377+
auto isStdlibDefaultImplDecl = [executorDecl](ValueDecl *witness) -> bool {
1378+
if (auto declContext = witness->getDeclContext()) {
1379+
if (auto *extension = dyn_cast<ExtensionDecl>(declContext)) {
1380+
if (auto extendedNominal = extension->getExtendedNominal()) {
1381+
return extendedNominal->getDeclaredInterfaceType()->isEqual(
1382+
executorDecl->getDeclaredInterfaceType());
1383+
}
1384+
}
1385+
}
1386+
return false;
1387+
};
1388+
auto missingWitness = !unownedEnqueueWitnessDecl &&
1389+
!moveOnlyEnqueueWitnessDecl &&
1390+
!legacyMoveOnlyEnqueueWitnessDecl;
1391+
1392+
bool unownedEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl);
1393+
bool moveOnlyEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl);
1394+
bool legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl = isStdlibDefaultImplDecl(legacyMoveOnlyEnqueueWitnessDecl);
1395+
auto allWitnessesAreDefaultImpls = unownedEnqueueWitnessIsDefaultImpl &&
1396+
moveOnlyEnqueueWitnessIsDefaultImpl &&
1397+
legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl;
1398+
if ((missingWitness) ||
1399+
(!missingWitness && allWitnessesAreDefaultImpls)) {
13811400
// Neither old nor new implementation have been found, but we provide default impls for them
13821401
// that are mutually recursive, so we must error and suggest implementing the right requirement.
13831402
//

test/Concurrency/custom_executor_enqueue_impls.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-move-only -disable-availability-checking
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking -verify-ignore-unknown
22
// REQUIRES: concurrency
33

44
// rdar://106849189 move-only types should be supported in freestanding mode

0 commit comments

Comments
 (0)