Skip to content

Commit b2f46ba

Browse files
authored
Merge pull request #67957 from ktoso/wip-dont-use-loc-validness-in-diagnostics-determination-113913291
[Executors] Do not consider Loc validity in determining to emit error/warning about enqueue(_:)
2 parents 5f5b68e + 5e43ba9 commit b2f46ba

File tree

4 files changed

+78
-23
lines changed

4 files changed

+78
-23
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6692,7 +6692,7 @@ WARNING(hashvalue_implementation,Deprecation,
66926692
"conform type %0 to 'Hashable' by implementing 'hash(into:)' instead",
66936693
(Type))
66946694

6695-
WARNING(executor_enqueue_unowned_implementation,Deprecation,
6695+
WARNING(executor_enqueue_deprecated_unowned_implementation,Deprecation,
66966696
"'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; "
66976697
"conform type %0 to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead",
66986698
(Type))

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,12 +1276,13 @@ 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() });
12821283

12831284
FuncDecl *moveOnlyEnqueueRequirement = nullptr;
1284-
FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr; // TODO: preferably we'd want to remove handling of `enqueue(Job)` when able to
1285+
FuncDecl *legacyMoveOnlyEnqueueRequirement = nullptr;
12851286
FuncDecl *unownedEnqueueRequirement = nullptr;
12861287
for (auto req: proto->getProtocolRequirements()) {
12871288
auto *funcDecl = dyn_cast<FuncDecl>(req);
@@ -1324,18 +1325,17 @@ 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+
ValueDecl *unownedEnqueueWitnessDecl = concreteConformance->getWitnessDecl(unownedEnqueueRequirement);
13291329
ValueDecl *moveOnlyEnqueueWitnessDecl = nullptr;
13301330
ValueDecl *legacyMoveOnlyEnqueueWitnessDecl = nullptr;
13311331

13321332
if (moveOnlyEnqueueRequirement) {
1333-
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1334-
moveOnlyEnqueueRequirement).getDecl();
1333+
moveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1334+
moveOnlyEnqueueRequirement);
13351335
}
13361336
if (legacyMoveOnlyEnqueueRequirement) {
1337-
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDeclRef(
1338-
legacyMoveOnlyEnqueueRequirement).getDecl();
1337+
legacyMoveOnlyEnqueueWitnessDecl = concreteConformance->getWitnessDecl(
1338+
legacyMoveOnlyEnqueueRequirement);
13391339
}
13401340

13411341
// --- Diagnose warnings and errors
@@ -1358,26 +1358,62 @@ void swift::tryDiagnoseExecutorConformance(ASTContext &C,
13581358
canRemoveOldDecls = declInfo.isContainedIn(requirementInfo);
13591359
}
13601360

1361+
auto concurrencyModule = C.getLoadedModule(C.Id_Concurrency);
1362+
auto isStdlibDefaultImplDecl = [executorDecl, concurrencyModule](ValueDecl *witness) -> bool {
1363+
if (auto declContext = witness->getDeclContext()) {
1364+
if (auto *extension = dyn_cast<ExtensionDecl>(declContext)) {
1365+
auto extensionModule = extension->getParentModule();
1366+
if (extensionModule != concurrencyModule) {
1367+
return false;
1368+
}
1369+
1370+
if (auto extendedNominal = extension->getExtendedNominal()) {
1371+
return extendedNominal->getDeclaredInterfaceType()->isEqual(
1372+
executorDecl->getDeclaredInterfaceType());
1373+
}
1374+
}
1375+
}
1376+
return false;
1377+
};
1378+
13611379
// If both old and new enqueue are implemented, but the old one cannot be removed,
13621380
// emit a warning that the new enqueue is unused.
1363-
if (!canRemoveOldDecls &&
1364-
unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid() &&
1365-
moveOnlyEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1366-
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unused_implementation);
1381+
if (!canRemoveOldDecls && unownedEnqueueWitnessDecl && moveOnlyEnqueueWitnessDecl) {
1382+
if (!isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl)) {
1383+
diags.diagnose(moveOnlyEnqueueWitnessDecl->getLoc(),
1384+
diag::executor_enqueue_unused_implementation);
1385+
}
13671386
}
13681387

13691388
// Old UnownedJob based impl is present, warn about it suggesting the new protocol requirement.
1370-
if (canRemoveOldDecls && unownedEnqueueWitnessDecl && unownedEnqueueWitnessDecl->getLoc().isValid()) {
1371-
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_unowned_implementation, nominalTy);
1389+
if (canRemoveOldDecls && unownedEnqueueWitnessDecl) {
1390+
if (!isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl)) {
1391+
diags.diagnose(unownedEnqueueWitnessDecl->getLoc(),
1392+
diag::executor_enqueue_deprecated_unowned_implementation,
1393+
nominalTy);
1394+
}
13721395
}
13731396
// Old Job based impl is present, warn about it suggesting the new protocol requirement.
1374-
if (legacyMoveOnlyEnqueueWitnessDecl && legacyMoveOnlyEnqueueWitnessDecl->getLoc().isValid()) {
1375-
diags.diagnose(legacyMoveOnlyEnqueueWitnessDecl->getLoc(), diag::executor_enqueue_deprecated_owned_job_implementation, nominalTy);
1397+
if (legacyMoveOnlyEnqueueWitnessDecl) {
1398+
if (!isStdlibDefaultImplDecl(legacyMoveOnlyEnqueueWitnessDecl)) {
1399+
diags.diagnose(legacyMoveOnlyEnqueueWitnessDecl->getLoc(),
1400+
diag::executor_enqueue_deprecated_owned_job_implementation,
1401+
nominalTy);
1402+
}
13761403
}
13771404

1378-
if ((!unownedEnqueueWitnessDecl || unownedEnqueueWitnessDecl->getLoc().isInvalid()) &&
1379-
(!moveOnlyEnqueueWitnessDecl || moveOnlyEnqueueWitnessDecl->getLoc().isInvalid()) &&
1380-
(!legacyMoveOnlyEnqueueWitnessDecl || legacyMoveOnlyEnqueueWitnessDecl->getLoc().isInvalid())) {
1405+
bool unownedEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(unownedEnqueueWitnessDecl);
1406+
bool moveOnlyEnqueueWitnessIsDefaultImpl = isStdlibDefaultImplDecl(moveOnlyEnqueueWitnessDecl);
1407+
bool legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl = isStdlibDefaultImplDecl(legacyMoveOnlyEnqueueWitnessDecl);
1408+
1409+
auto missingWitness = !unownedEnqueueWitnessDecl &&
1410+
!moveOnlyEnqueueWitnessDecl &&
1411+
!legacyMoveOnlyEnqueueWitnessDecl;
1412+
auto allWitnessesAreDefaultImpls = unownedEnqueueWitnessIsDefaultImpl &&
1413+
moveOnlyEnqueueWitnessIsDefaultImpl &&
1414+
legacyMoveOnlyEnqueueWitnessDeclIsDefaultImpl;
1415+
if ((missingWitness) ||
1416+
(!missingWitness && allWitnessesAreDefaultImpls)) {
13811417
// Neither old nor new implementation have been found, but we provide default impls for them
13821418
// that are mutually recursive, so we must error and suggest implementing the right requirement.
13831419
//
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-typecheck-verify-swift -disable-availability-checking
2+
// REQUIRES: concurrency
3+
4+
// rdar://106849189 move-only types should be supported in freestanding mode
5+
// UNSUPPORTED: freestanding
6+
7+
8+
extension Executor {
9+
func enqueue(_ job: UnownedJob) { // expected-warning{{'Executor.enqueue(UnownedJob)' is deprecated as a protocol requirement; conform type 'NoneExecutor' to 'Executor' by implementing 'func enqueue(ExecutorJob)' instead}}
10+
fatalError()
11+
}
12+
}
13+
14+
final class NoneExecutor: SerialExecutor {
15+
16+
// the enqueue from the extension is properly picked up,
17+
// even though we do warn about deprecation on it in the extension.
18+
19+
func asUnownedSerialExecutor() -> UnownedSerialExecutor {
20+
UnownedSerialExecutor(ordinary: self)
21+
}
22+
}

test/Concurrency/custom_executor_enqueue_impls.swift

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

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

7-
// FIXME: rdar://107112715 test failing on iOS simulator, investigating
8-
// UNSUPPORTED: OS=ios
9-
107
// Such type may be encountered since Swift 5.5 (5.1 backdeployed) if someone implemented the
118
// not documented, but public Executor types back then already.
129
//

0 commit comments

Comments
 (0)